在 Android 中, 混淆是基础且必不可少的一环,混淆功能对我们来说意义重大。
混淆的意义
1、混淆会将方法名,类名等修改为 a, b 等代号, 大大提升代码被破解难度,从而减少代码泄漏的风险,提升代码的安全性;
2、混淆会移除未使用的代码和资源,且混淆后包名,类名等进行了缩减,从而缩小了包的体积;
3、混淆会对代码进行优化和压缩,从而提高应用程序的性能。优化包括删除未使用的方法和变量,压缩包括将代码中的常量和字符串替换为相应的字节码表示
因此,在打 release 包的时候,能使用混淆就建议使用混淆。
混淆的使用
开启
混淆的开启和关闭可以在 build.gradle 进行配置
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
minifyEnabled 属性为一个 boolean 值,如果不设置,默认为 false, 不使用混淆,需要开启时将其属性改为 true 即可。
proguardFiles 属性用来指定混淆的配置文件地址, 默认会指向 app 目录下的 proguard-rules.pro 文件,因此一般只需要在此文件中配置混淆的规则就可以了。
混淆的规则
并不是所有的代码都可以进行混淆的,譬如提供给第三方调用的接口(一般是开发 sdk 或者 aar),需要通过反射来调用的方法和类等就不能混淆。
而且在引入一些三方库的时候,有时也会需要配置混淆规则,而这些混淆规则,需要在 proguard-rules.pro 文件下进行配置。
下面展示一些较为常用的 proguard-rules.pro 语法。
# 具体的类
-keep class com.xxx.xxxClass
# * 表示匹配任意字符但是不包含 .
-keep class com.xxx.xxx.*
# ** 表示匹配任意字符
-keep class com.xxx.xxx.**
# extends implements 对继承/实现某个类的类不混淆
-keep class * extends com.xxx.xxx
-keep class * implements com.xxx.xxx
# public private protect 等修饰符同样可以进行限制
-keep public class * extends com.xxx.xxx
# 不混淆类及其成员
-keep class com.xxx.xxx.** {*;}
# 不混淆类及其特定规则的成员
-keepclassmembers class com.xxx.xxxClass {
# 不混淆具体的某个方法
public java.lang.String getXXX(android.content.Context);
# 不混淆其构造方法
public <init>();
# 不混淆 public 修饰的 get 方法
public * get*();
# 不混淆满足某一个规则的字段
!private <fields>;
static <fields>;
public <methods>;
}
# 保留特定的属性 个人理解可以通过 -keepclassmembers 来实现
# 保留包含特定属性的类
-keepattributes InnerClasses {
class com.xxx.xxxClass
}
#保留包含特定成员的类
-keepclasseswithmembers class com.xxx.xxxClass {
public <init>(java.lang.String);
}
#保留包含特定成员名称的类
-keepclasseswithmembernames class * {
public java.lang.String uid;
}
# 禁止混淆工具发出警告 通畅要和其他 class 搭配使用
-dontwarn com.xxx.xxxClass
# 保持枚举类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
基本上较为常用的混淆规则都在上面列出来了,掌握后面对日产的混淆配置基本都能搞定,如果后续过程中遇到其他的较为常用的混淆,笔者会继续更新配置。