Confusão de empacotamento do Android Studio e regras gramaticais

Ao usar o Android Studio para confundir e empacotar, o próprio Studio integra o ProGuard da linguagem Java como uma ferramenta de compactação, otimização e ofuscação, e é muito fácil de usar com a ferramenta de compilação Gradle. Basta definir minifyEnabled como true no arquivo gradle do diretório do aplicativo do projeto. Em seguida, podemos adicionar nossas regras de ofuscação ao arquivo proguard-rules.pro.

Compactação do efeito ProGuard
(encolhimento) : ativado por padrão para reduzir o tamanho do aplicativo, remover classes e membros não utilizados e executar novamente após a execução da ação de otimização (porque algumas classes não utilizadas podem ser expostas novamente após a otimização e os membros). Se você deseja desativar a compactação, adicione ao arquivo proguard-rules.pro:

# 关闭压缩
-dontshrink 

Otimização : habilitada por padrão, a otimização é executada no nível do bytecode para tornar o aplicativo mais rápido. Igual ao anterior, se você quiser desativar a otimização, adicione o arquivo proguard-rules.pro:

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

Ofuscação : Ativado por padrão, o que aumenta a dificuldade de descompilação. As classes e os membros da classe serão nomeados aleatoriamente, a menos que sejam protegidos por keep.

# 关闭混淆
-dontobfuscate

Após a ofuscação, um arquivo mapping.txt será gerado no diretório do projeto app/build/outputs/mapping/release por padrão. Esta é a regra de ofuscação. Podemos enviar o código ofuscado de volta ao código-fonte de acordo com este arquivo, então este arquivo Muito importante, preste atenção para proteger bem. A princípio quanto mais caótico e irregular for o código após a ofuscação, melhor, mas precisamos evitar confusão em alguns lugares, caso contrário o programa rodará errado, então vou te ensinar a seguir, como evitar a ofuscação de parte do seu código para evitar erros.

Ative a ofuscação no código:
modifique minifyEnabled false para true no arquivo build.gradle no módulo do aplicativo.
Você também pode definir para excluir recursos inúteis ao mesmo tempo. (Excluir recurso inútil)

 Depois de modificar aqui, você precisa operar o arquivo proguard-rules.pro no módulo app para definir as opções de ofuscação para empacotamento do projeto:

A seguir estão meus modelos de ofuscação comumente usados, que podem ser adicionados ou excluídos de acordo com as necessidades reais:
 


#--------------------------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

Algumas regras básicas para ofuscação:

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

Uma estrela 
  significa que apenas os nomes de classe sob o pacote são mantidos, e os nomes de classe sob os subpacotes ainda serão confundidos; duas 
estrelas 
  significa que ambos os nomes de classe sob este pacote e os subpacotes são mantidos; depois de usar o método acima para manter a classe, você descobrirá que, embora o nome da classe não esteja confuso, o método específico e a nomenclatura da variável interna foram alterados. 

Se você quiser manter o nome da classe e evitar que o conteúdo seja confuso, use:
 

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

Com base nisso, também podemos usar as regras básicas de Java para evitar que classes específicas sejam confundidas, por exemplo, podemos usar regras de Java como extends e implements. O exemplo a seguir evita que todas as classes herdadas de Activity sejam confundidas

-keep public class * extends android.app.Activity

Se quisermos evitar que a classe interna de uma classe seja confusa, precisamos usar o símbolo $. O exemplo a seguir significa impedir que todo o conteúdo público na classe interna JavaScriptInterface XxFragment seja confundido.

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

Se você não deseja evitar que todo o conteúdo de uma classe seja confuso, mas apenas deseja proteger o conteúdo específico da classe, você pode usar

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

Você também pode adicionar private, public, native, etc. na frente de <fields> ou <methods> para especificar melhor o conteúdo que não será confundido. Por exemplo, o código a seguir significa que todos os métodos Public sob a classe chamada Demo serão não se confunda.

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

Por exemplo, o código a seguir indica que o construtor com JSONObject como parâmetro de entrada não será confundido

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

Se você não precisa manter o nome da classe, você só precisa evitar que o método específico da classe seja confundido, então você não pode usar o método Keep, o método Keep manterá o nome da classe, mas você precisa use keepclassmembers, então o nome da classe não será mantido.

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

Precauções

1. O método jni não pode ser confundido, pois este método precisa ser consistente com o método nativo;

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

2. As classes usadas pela reflexão não são confundidas (caso contrário pode haver problemas com a reflexão);

3. As classes no AndroidMainfest não são confusas, então os quatro principais componentes e subclasses de Application e todas as classes sob a camada Framework não serão confundidas por padrão, e a Visualização personalizada não será confusa por padrão. Portanto, muitas regras que excluem visualizações personalizadas postadas na Internet, ou os quatro principais componentes são confusos, não precisam ser adicionadas no Android Studio.

4. Ao interagir com o servidor, ao usar GSON, fastjson e outras estruturas para analisar os dados do servidor, a classe de objeto JSON escrita não é confusa, caso contrário, o JSON não pode ser analisado nos objetos correspondentes;

5. Ao usar uma biblioteca de código aberto de terceiros ou fazer referência a outros pacotes SDK de terceiros, se houver requisitos especiais, também é necessário adicionar regras de ofuscação correspondentes ao arquivo de ofuscação;

6. As chamadas JS que usam WebView também precisam garantir que os métodos de interface escritos não sejam confundidos, o motivo é o mesmo do primeiro;

7. A subclasse de Parcelable não se confunde com a variável membro static de Creator, caso contrário será gerado Android.os.BadParcelableException;

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

8. Ao usar o tipo enum, você precisa prestar atenção para evitar a confusão dos dois métodos a seguir. Devido à particularidade da classe enum, os dois métodos a seguir serão chamados por reflexão, consulte a segunda regra.

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

Além de definir minifyEnabled como true ao lançar um aplicativo, você também deve definir zipAlignEnabled como true . Por exemplo, o Google Play força os desenvolvedores a fazer upload de aplicativos que devem ser zipAligned. ZipAlign pode alinhar os recursos no pacote de instalação por 4 bytes, o que pode reduzir o consumo de memória do aplicativo em tempo de execução.

Referência:
confusão de empacotamento do Android e regras de sintaxe detalhadas_wx60e80a6332641's blog técnico_51CTO blog

Acho que você gosta

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