Confusión de empaquetado de Android Studio y reglas gramaticales

Cuando se usa Android Studio para confundir y empaquetar, el mismo Studio integra ProGuard del lenguaje Java como una herramienta de compresión, optimización y ofuscación, y es muy fácil de usar con la herramienta de compilación Gradle. Simplemente establezca minifyEnabled en verdadero en el archivo gradle del directorio de la aplicación del proyecto. Luego podemos agregar nuestras reglas de ofuscación al archivo proguard-rules.pro.

Compresión del efecto ProGuard
(reducción) : habilitado de forma predeterminada para reducir el tamaño de la aplicación, eliminar clases y miembros no utilizados y ejecutarla nuevamente después de ejecutar la acción de optimización (porque algunas clases no utilizadas pueden quedar expuestas nuevamente después de la optimización) y miembros). Si desea desactivar la compresión, agregue al archivo proguard-rules.pro:

# 关闭压缩
-dontshrink 

Optimización : habilitada de forma predeterminada, la optimización se realiza a nivel de código de bytes para que la aplicación se ejecute más rápido. Igual que arriba, si desea desactivar la optimización, agregue el archivo proguard-rules.pro:

# 关闭优化
-dontoptimize
-optimizationpasses n 表示proguard对代码进行迭代优化的次数,Android一般为5

Ofuscación : habilitado de forma predeterminada, lo que aumenta la dificultad de la descompilación. Las clases y los miembros de la clase se nombrarán aleatoriamente a menos que estén protegidos por Keep.

# 关闭混淆
-dontobfuscate

Después de la ofuscación, se generará un archivo mapping.txt en el directorio del proyecto app/build/outputs/mapping/release de forma predeterminada. Esta es la regla de ofuscación. Podemos enviar el código ofuscado de vuelta al código fuente de acuerdo con este archivo, por lo que este archivo Muy importante, presta atención para protegerlo bien. En principio, cuanto más caótico e irregular sea el código después de la ofuscación, mejor, pero debemos evitar confusiones en algunos lugares, de lo contrario, el programa funcionará mal, por lo que te enseñaré lo siguiente, cómo evitar que parte de tu código sea ofuscado. y así prevenir errores.

Habilite la ofuscación en el código:
modifique minifyEnabled falso a verdadero en el archivo build.gradle en el módulo de la aplicación.
También puede configurar para eliminar recursos inútiles al mismo tiempo. (Eliminar recurso inútil)

 Después de modificar aquí, debe operar el archivo proguard-rules.pro en el módulo de la aplicación para definir las opciones de ofuscación para el empaquetado del proyecto:

Las siguientes son mis plantillas de ofuscación de uso común, que se pueden agregar o eliminar según las necesidades reales:
 


#--------------------------1.实体类 ↓---------------------------------
-keep public class com.XX.XX.bean.** { *; }

#--------------------------1.实体类 ↑---------------------------------


#--------------------------2.第三方包 ↓-------------------------------
# Glide
-keep public class * implements com.bumptech.glide.module.AppGlideModule
-keep public class * implements com.bumptech.glide.module.LibraryGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
#gson
-keep class com.google.gson.** { *; }
-keep class com.google.**{ *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }


#retrofit2
-dontwarn javax.annotation.**
-dontwarn javax.inject.**
# OkHttp3
-dontwarn okhttp3.logging.**
-keep class okhttp3.internal.**{*;}
-dontwarn okio.**
# Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
# RxJava RxAndroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
    long producerIndex;
    long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode consumerNode;
}

# eventbus
-keepattributes *Annotation*
-keepclassmembers class * {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

#--------------------------2.第三方包 ↑-------------------------------


#--------------------------3.与js互相调用的类 ↓------------------------
-keep class **.AndroidJavaScript { *; }
-keepclassmembers class * extends android.webkit.WebViewClient {
     public void *(android.webkit.WebView,java.lang.String,android.graphics.Bitmap);
     public boolean *(android.webkit.WebView,java.lang.String);
}
-keepclassmembers class * extends android.webkit.WebChromeClient {
     public void *(android.webkit.WebView,java.lang.String);
}
-keepattributes JavascriptInterface
#-------------------------3.与js互相调用的类 ↑------------------------


#-------------------------4.基本不用动区域 ↓--------------------------
#指定代码的压缩级别
-optimizationpasses 5

#包明不混合大小写
-dontusemixedcaseclassnames

#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers

#混淆时是否记录日志
-verbose

#优化  不优化输入的类文件
-dontoptimize

#预校验
-dontpreverify

# 保留sdk系统自带的一些内容 【例如:-keepattributes *Annotation* 会保留Activity的被@override注释的onCreate、onDestroy方法等】
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

# 记录生成的日志数据,gradle build时在本项根目录输出
# apk 包内所有 class 的内部结构
-dump proguard/class_files.txt
# 未混淆的类和成员
-printseeds proguard/seeds.txt
# 列出从 apk 中删除的代码
-printusage proguard/unused.txt
# 混淆前后的映射
-printmapping proguard/mapping.txt


# 避免混淆泛型
-keepattributes Signature
# 抛出异常时保留代码行号,保持源文件以及行号
-keepattributes SourceFile,LineNumberTable
#-------------------------4.基本不用动区域 ↑--------------------------

#-------------------------5.默认保留区 ↓-----------------------
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclassmembers public class * extends android.view.View {
 public <init>(android.content.Context);
 public <init>(android.content.Context, android.util.AttributeSet);
 public <init>(android.content.Context, android.util.AttributeSet, int);
 public void set*(***);
}

#保持 Serializable 不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
    public <init>(android.content.Context,android.util.AttributeSet);
}
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
    public <init>(android.content.Context,android.util.AttributeSet,int);
}
# 保持自定义控件类不被混淆
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}

# 保持枚举 enum 类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

# 不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了。
-keepclassmembers class **.R$* {
    public static <fields>;
}

#如果引用了v4或者v7包
-dontwarn android.support.**

# 保持哪些类不被混淆
-keep public class * extends android.app.Application
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
#-------------------------5.默认保留区 ↑-----------------------


# ============忽略警告,否则打包可能会不成功=============
-ignorewarnings

Algunas reglas básicas para la ofuscación:

-keep class com.XX.test.**
-keep class com.XX.test.*

Una estrella 
  significa que solo se conservan los nombres de las clases del paquete, y los nombres de las clases de los subpaquetes se seguirán confundiendo; 
dos estrellas 
  significan que se conservan los nombres de las clases de este paquete y los subpaquetes; después de usar lo anterior para mantener la clase, encontrará que aunque el nombre de la clase no se confunde, el método específico y el nombre de la variable dentro han cambiado. 

Si desea mantener el nombre de la clase y evitar que el contenido interno se confunda, use:
 

-keep class com.XX.test.* {*;}

Sobre esta base, también podemos usar las reglas básicas de Java para evitar que se confundan clases específicas.Por ejemplo, podemos usar reglas de Java como extends e implements. El siguiente ejemplo evita que se confundan todas las clases que heredan de Activity

-keep public class * extends android.app.Activity

Si queremos evitar que la clase interna en una clase se confunda, debemos usar el símbolo $. El siguiente ejemplo significa evitar que se confunda todo el contenido público en la interfaz de JavaScript de la clase interna de XxFragment.

-keepclassmembers class com.XX.ui.fragment.XxFragment$JavaScriptInterface {
   public *;
}

Si no desea evitar que todo el contenido de una clase se confunda, pero solo desea proteger el contenido específico de la clase, puede usar

<init>;     //匹配所有构造器
<fields>;   //匹配所有域
<methods>;  //匹配所有方法方法

También puede agregar privados, públicos, nativos, etc. delante de <campos> o <métodos> para especificar aún más el contenido que no se confundirá. Por ejemplo, el siguiente código significa que todos los métodos públicos de la clase denominada Demo no se confunda

-keep class com.XX.test.Demo {
    public <methods>;
}

Por ejemplo, el siguiente código indica que el constructor con JSONObject como parámetro de entrada no se confundirá

-keep class com.XX.test.Demo {
   public <init>(org.json.JSONObject);
}

Si no necesita mantener el nombre de la clase, solo necesita evitar que los métodos específicos de la clase se confundan, entonces no puede usar el método de mantenimiento. El método de mantenimiento mantendrá el nombre de la clase, pero debe use keepclassmembers, por lo que el nombre de la clase no se mantendrá.

# -keep关键字
# keep:包留类和类中的成员,防止他们被混淆
# keepnames:保留类和类中的成员防止被混淆,但成员如果没有被引用将被删除
# keepclassmembers :只保留类中的成员,防止被混淆和移除。
# keepclassmembernames:只保留类中的成员,但如果成员没有被引用将被删除。
# keepclasseswithmembers:如果当前类中包含指定的方法,则保留类和类成员,否则将被混淆。
# keepclasseswithmembernames:如果当前类中包含指定的方法,则保留类和类成员,如果类成员没有被引用,则会被移除。

Precauciones

1. El método jni no se puede confundir, porque este método debe ser consistente con el método nativo;

# 保持native方法不被混淆 
-keepclasseswithmembernames class * {    
    native <methods>;
}

2. Las clases utilizadas por la reflexión no se confunden (de lo contrario, puede haber problemas con la reflexión);

3. Las clases en AndroidMainfest no se confunden, por lo que los cuatro componentes principales y las subclases de la aplicación y todas las clases de la capa Framework no se confundirán de forma predeterminada, y la vista personalizada no se confundirá de forma predeterminada. Por lo tanto, no es necesario agregar en Android Studio muchas reglas que excluyen las vistas personalizadas publicadas en Internet o que se confunden los cuatro componentes principales.

4. Al interactuar con el servidor, al usar GSON, fastjson y otros marcos para analizar los datos del servidor, la clase de objeto JSON escrito no se confunde; de ​​lo contrario, JSON no se puede analizar en los objetos correspondientes;

5. Al utilizar una biblioteca de código abierto de terceros o hacer referencia a otros paquetes SDK de terceros, si existen requisitos especiales, también es necesario agregar las reglas de ofuscación correspondientes al archivo de ofuscación;

6. Las llamadas JS que usan WebView también deben asegurarse de que los métodos de interfaz escritos no se confundan, la razón es la misma que la primera;

7. La subclase de Parcelable no se confunde con la variable miembro estática de Creator; de lo contrario, se generará Android.os.BadParcelableException;

# 保持Parcelable不被混淆    
-keep class * implements Android.os.Parcelable {         
    public static final Android.os.Parcelable$Creator *;
}

8. Al usar el tipo de enumeración, debe prestar atención para evitar la confusión de los dos métodos siguientes. Debido a la particularidad de la clase de enumeración, los dos métodos siguientes se llamarán por reflexión, consulte la segunda regla.

-keepclassmembers enum * {  
    public static **[] values();  
    public static ** valueOf(java.lang.String);  
}

Además de establecer minifyEnabled en true al publicar una aplicación, también debe establecer zipAlignEnabled en true . Por ejemplo, Google Play obliga a los desarrolladores a cargar aplicaciones que deben estar zipAligned. ZipAlign puede alinear los recursos en el paquete de instalación en 4 bytes, lo que puede Reducir el consumo de memoria de la aplicación en tiempo de ejecución.

Referencia:
Confusión de empaquetado de Android y reglas gramaticales detalladas_wx60e80a6332641's Technical Blog_51CTO blog

Supongo que te gusta

Origin blog.csdn.net/NewActivity/article/details/125085305
Recomendado
Clasificación