打开混淆:
release {
//打开混淆
minifyEnabled true
//打开资源压缩
shrinkResources true
//不显示log
buildConfigField "boolean", "LOG_DEBUG", "true"
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
在app下的build.gradle 文件中 设置minifyEnabled true 即可打开混淆。
混淆文件配置:
混淆关键字:
关键字 | 描述 |
---|---|
keep | 保留类和类成员 |
keepnames | 保留类和类成员但没有被引用的类成员会被移除 |
keepclassmembers | 只保留类成员 |
keepclassmembernames | 只保留类成员但没有被引用的成员会被移除 |
keepclasseswithmember | 保留类和类成员,保留指明的成员 |
keepclasseswithmembernames | 保留类和类成员,保留指明成员,成员没有引用则移除 |
总结:name:无引用成员删除,members:只保留成员,with:保留指明成员。
dontwarn: 一般在引入library时配合keep使用,引入的library可能存在一些无法找到的引用和其他问题,在Build时可能会发出警告,不处理的话会导致编译中止,为了保证编译继续使用dontwarn处理。
混淆通配符:
通配符 | 描述 |
---|---|
匹配类中所有字段 | |
匹配类中所有方法 | |
匹配类中所有构造函数 | |
* | 匹配任意长度字符,但不包括分隔符. 只保留当前包,子包还是会被混淆 eg:com.android.view =>com.android.* com.*则不可匹配 |
** | 匹配任意长度字符,包含分隔符 . 保留当前包和所有子包 |
*** | 匹配任意参数类型 eg:getName(***) |
一些不应混淆的东西:
- 使用了自定义控件那么要保证它们不参与混淆使用了枚举要保证枚举不被混淆
- 对第三方库中的类不进行混淆
- 运用了反射的类也不进行混淆
- 使用了 Gson 之类的工具要使 JavaBean 类即实体类不被混淆
- 在引用第三方库的时候,一般会标明库的混淆规则的,建议在使用的时候就把混淆规则添加上去,免得到最后才去找
- 有用到 WebView 的 JS 调用也需要保证写的接口方法不混淆,原因和第一条一样
- Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常
- 使用的四大组件,自定义的Application* 实体类
- JNI中调用的类
- Layout布局使用的View构造函数(自定义控件)、android:onClick等。
混淆模板:
# ------------------------------基本指令区---------------------------------
-optimizationpasses 5 #指定压缩级别
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #混淆时采用的算法
-verbose #打印混淆的详细信息
-dontoptimize #关闭优化
-dontpreverify #不进行预校验,可加快混淆速度
-keepattributes *Annotation* #保留注解中的参数
-keepattributes Signature # 避免混淆泛型, 这在JSON实体映射时非常重要
-ignorewarnings # 屏蔽警告
-dontskipnonpubliclibraryclasses # 指定不去忽略非公共的库类(不跳过library中的非public的类)
-dontskipnonpubliclibraryclassmembers # 指定不去忽略包可见的库类的成员
-keepattributes SourceFile,LineNumberTable # 抛出异常时保留代码行号
-printmapping proguardMapping.txt
# -------------------------------基本指令区--------------------------------
#---------------------------------默认保留区---------------------------------
#继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-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
-keep public class * extends android.view.View
-keep class android.support.** {*;}
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
#表示不混淆上面声明的类,最后这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。
#不混淆View中的set***() 和 get***()方法 以保证属性动画正常工作 某个类中的某个方法不混淆
#自定义View的set get方法 和 构造方法不混淆
-keep public class * extends android.view.View{
*** get*();
void set*(***);
public (android.content.Context);
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
}
#这个主要是在layout 中写的onclick方法android:onclick="onClick",不进行混淆
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#实现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();
}
# 保留R文件中所有静态字段,以保证正确找到每个资源的ID
-keepclassmembers class **.R$* {
public static ;
}
-keepclassmembers class * {
void *(*Event);
}
#保留枚举类中的values和valueOf方法
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#保留Parcelable实现类中的Creator字段,以保证Parcelable机制正常工作
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#// natvie 方法不混淆
-keepclasseswithmembernames class * {
native ;
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#不混淆包含native方法的类的类名以及native方法名
-keepclasseswithmembernames class * {
native;
}
#对含有反射类的处理
-dontwarn com.suchengkeji.android.confusiondemo.md.**
-keep class com.suchengkeji.android.confusiondemo.md.** { *; }
#--------------------------------默认保留区--------------------------------------------
#----------------------------- WebView(项目中没有可以忽略) -----------------------------
#
#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, jav.lang.String);
}
#在app中与HTML5的JavaScript的交互进行特殊处理
#我们需要确保这些js要调用的原生方法不能够被混淆,于是我们需要做如下处理:
-keepclassmembers class com.ljd.example.JSInterface {
;
}
#----------------------------- WebView(项目中没有可以忽略) -----------------------------
#----------------------------- 实体类不可混淆 ------------------------------------------
#----------------------------- 添加实体类混淆规则 ---------------------------------------
#----------------------------- 实体类不可混淆 ------------------------------------------
#----------------------------- 第三方类库 ------------------------------------------
#----------------------------- 添加第三方类库的混淆规则 ---------------------------------------
#----------------------------- 第三方类库 ------------------------------------------
本文摘录自:https://www.jianshu.com/p/b5b2a5dfaaf4
如有需要请移步原文。