Android开发中掌握混淆规则是必备技能之一。
混淆方式
主module中统一配置
这种情况简单,针对自己项目代码和三方库代码编写混淆规则即可。当取消某些module依赖时,需要剔除响应的混淆规则,较麻烦。
各module单独配置
随着项目不断扩大,多个module同时存在的项目已很普遍。
主module配置一些通用的混淆规则。
-
子module在gradle中配置consumerProguardFiles属性来指定混淆文件就可以。
// 子模块单独配置混淆规则 buildTypes { release { consumerProguardFiles 'proguard-rules.pro' } }
proguard使用及规则
主module开启混淆配置
android {
...
buildTypes {
release {
// zipAlign可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。
zipAlignEnabled true
// 压缩资源
shrinkResources true
// 开启混淆
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
通用规则
#指定压缩级别
-optimizationpasses 5
#不跳过非公共的库的类成员
-dontskipnonpubliclibraryclassmembers
#混淆时采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#把混淆类中的方法名也混淆了
-useuniqueclassmembernames
#优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification
#将文件来源重命名为“SourceFile”字符串
-renamesourcefileattribute SourceFile
#保留行号
-keepattributes SourceFile,LineNumberTable
#保持泛型
-keepattributes Signature
#保持所有实现 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();
}
#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native <methods>;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
# 保持Parcelable不被混淆
public static final android.os.Parcelable$Creator CREATOR;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**
# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep
-keep @android.support.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@android.support.annotation.Keep <init>(...);
}
# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**
哪些需要添加keep规则
- 三方库
- 反射代码
- JNI native代码
- webview js注入方法相关类
自定义规则及语法
- 不混淆某个类
-keep public class name.huihui.example.Test { *; }
- 不混淆某个包所有的类
-keep class name.huihui.test.** { *; }
- 不混淆某个类的子类
-keep public class * extends name.huihui.example.Test { *; }
- 不混淆所有类名中包含了“model”的类及其成员
-keep public class **.*model*.** {*;}
- 不混淆某个接口的实现
-keep class * implements name.huihui.example.TestInterface { *; }
- 不混淆某个类的构造方法
-keepclassmembers class name.huihui.example.Test {
<init>; #匹配所有构造器
<fields>;#匹配所有域
<methods>;#匹配所有方法}
public void test(java.lang.String); # 特定方法
public <methods>;#保持该类下所有的共有方法不被混淆
public *;#保持该类下所有的共有内容不被混淆
private <methods>;#保持该类下所有的私有方法不被混淆
private *;#保持该类下所有的私有内容不被混淆
public <init>(java.lang.String);#保持该类的String类型的构造方法
}
- 不混淆某个类的内部类
-keep class name.huihui.example.Test$* {
*;
}