配置说明
保留选项
-keep {Modifier} {class_specification} 保护指定的类文件和类的成员
-keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好
-keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
-keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)
-keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除)
-keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
-printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件
压缩
-dontshrink 不压缩输入的类文件
-printusage {filename}
-whyareyoukeeping {class_specification}
优化
-dontoptimize 不优化输入的类文件
-assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用
-allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员
混淆
-dontobfuscate 不混淆输入的类文件
-printmapping {filename}
-applymapping {filename} 重用映射增加混淆
-obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称
-overloadaggressively 混淆时应用侵入式重载
-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆
-flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中
-repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中
-dontusemixedcaseclassnames 混淆时不会产生形形色色的类名
-keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
-renamesourcefileattribute {string} 设置源文件中给定的字符串常量
屏蔽警告信息
-dontwarn 不对指定的类、包中的不完整的引用发出警告
通用配置
#代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses 5
#把混淆类中的方法名也混淆了
-useuniqueclassmembernames
#优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification
# 避免混淆内部类、泛型、匿名类
-keepattributes InnerClasses,Signature,EnclosingMethod
#抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
#重命名抛出异常时的文件名称为"SourceFile"
-renamesourcefileattribute SourceFile
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持所有实现 Serializable 接口的类成员
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#保留JNI类
-keepclasseswithmembernames class * {
native <methods>;
}
#不混淆资源类
-keepclassmembers class **.R$* {
public static <fields>;
}
#保留使用的四大组件,自定义的Application等等这些类不被混淆
#因为这些子类都有可能被外部调用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
#保留support下的所有类及其内部类
-keep class android.support.** {*;}
# 保留继承的support类
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
#保留们自定义控件(继承自View)不被混淆
-keep public class * extends android.view.View{
*** get*();
void set*(***);
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下
-keep public class * extends android.app.Fragment
# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**
针对App的配置
实体类需要保留,实体类的get和set方法(尤其是反射会用到的,不保留可能有些json解析不匹配),boolean类型的get方法是isXXX,不要忘记保留。
-keep public class com.dev.example.entity.** {
public void set*(***);
public *** get*();
public *** is*();
}
注意:保留实体类时也可以按照类名所包含某些字母来筛选,如(名字中带有Model的):
-keep public class **.*Model*.** {
public void set*(***);
public *** get*();
public *** is*();
}
保留写在某个类里面的所有内部类,如以下类A中所有的内部类将会被保留
-keep class com.dev.example.A$* { *; }
其中{*;}匹配该类里面的所有部分
如果要保留内部类中的内部类则可以连续拼上$符号,如(保留类A中内部类B中的内部类):
-keep class com.dev.example.A$B$* { *; }
对webView进行处理
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
-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.webViewClient {
public void *(android.webkit.webView, java.lang.String);
}
如果我们的app中涉及到和h5交互,需要保留js调用的原生方法
# Keep JavascriptInterface
-keepclassmembers class ** {
@android.webkit.JavascriptInterface public *;
}
对含有反射类的处理,有时候项目中有些类不是实体类,但仍然用到反射功能,如Class.forName(“xxx”),这是我们需要保留的。比如这些类在com.dev.example包下,可以通过下面的配置进行保留。
-keep class com.dev.example.* { *; }
另外上面只是保留了该包下的类,如果该包下还有子包,则子包的类仍然会被混淆,
如果想保留该包下子包的类,我们可以如下配置(**能匹配本包和所含子包,其中子包也可以含有子包)
-keep class com.dev.example.**{ *; }
常见的自定义的配置
1.保留某个特定的类
#保留Test类
-keep public class com.dev.example.Test { *; }
2.保留某个类的子类
#保留继承了AbstractClass的子类
-keep class * extends com.dev.example.AbstractClass{*;}
3.保留接口的实现类
#保留实现了Callable接口的类
-keep class * implements Callable{*;}
4.保留类的特定部分,如:保留TaskRepository类的所有构造方法,变量和普通方法。
-keep class com.dev.example.TaskRepository{
<init>; //匹配所有构造器
<fields>; //匹配所有域
<methods>; //匹配所有方法
}
还可以保留的更具体一点,如下所示
-keepclassmembers com.dev.example.TaskRepository{
// 保留该类的修饰符是public且有一个参数(类型是String)的构造方法
public <init>(java.lang.String);
// 保留该类的所有修饰符是public且返回类型void的方法
public void *(**);
// 保留该类的具体某一个方法
public String getUserName();
}
常见的第三方库
#okhttp
-dontwarn com.squareup.okhttp.**
-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okio.**
#retroift
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
# fresco SDK
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
@com.facebook.common.internal.DoNotStrip *;
}
#rx
-dontwarn rx.**
-keep class rx.** { *;}
#keep GSON stuff
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.** { *; }
#ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
#enventbus
-keep class org.greenrobot.eventbus.** { *;}
-dontwarn org.greenrobot.eventbus.**
-keepclassmembers class ** {
public void onEvent*(**);
}
# Bugly
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
# aliyun push
-keepclasseswithmembernames class ** {
native <methods>;
}
# QQ share SDK
-dontwarn com.tencent.**
-keepnames class com.tencent.** {*;}
# sina share SDK
-dontwarn com.sina.**
-keepnames class com.sina.** {*;}
# umeng SDK
-keep public class * extends com.umeng.**
-dontwarn com.umeng.**
-keep class com.umeng.** { *; }
不混淆规则
1、反射用到的类不能混淆,JNI方法不混淆
2、AndroidMainfest中的类不混淆
3、四大组件和Application的子类和Framework 层下所有的类默认不会进行混淆
4、Parcelable的子类和Creator 静态成员变量不混淆,否则会产生 android.os.BadParcelableException 异常
5、使用GSON、fastjson等框架时,所写的JSON 对象类不混淆,否则无法将JSON解析成对应的对象
6、使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则
7、有用到WebView的JS调用也需要保证写的接口方法不混淆