Android 中 ProGuard 混淆详解(二)

本文详细介绍了Android项目中使用ProGuard进行代码混淆的方法,涵盖了混淆的基本配置、资源压缩、自定义混淆规则等内容,并提供了实用的混淆命令示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

在上一篇文章中,只是介绍了ProGuard混淆的基本配置,和混淆结果文件的查看。代码混淆包含了四个过程,压缩,优化,混淆,预校验等。这四个过程默认是开启的,在Android 项目中,我们可以选择将“优化”和“预校验”关闭,对应的命令是“-dontoptimize” 和“-dontpreverify”,sdk中默认的proguard-android.txt 文件已经包含这两个混淆命令,不需要额外配置。

资源压缩

资源压缩将移除项目及依赖的库中没有被使用的资源,这将会减少apk包体积会有不同的效果,一般建议开启。
release {
… .
minifyEnabled true
shrinkResources true
… .
}
注意:只有在minifyEnabled true 开启代码压缩后,资源压缩才会生效。

自定义混淆规则
build.gradle文件中包含了,proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
上面代码表示了混淆规则由两部分构成:位于sdk中tools/proguard 目录下的 proguard-android.txt的内容以及默认放置于模块根目录的proguard-rules.pro文件的内容。前者是SDK提供的默认混淆文件,后者是开发者自定义混淆规则的地方。

常见混淆命令

● optimizationpasses
● dontoptimize
● dontusemixedcaseclassnames
● dontskipnonpubliclibraryclasses
● dontpreverify
● dontwarn
● verbose
● optimizations
● keep
● keepnames
● keepclassmembers
● keepclassmembernames
● keepclasseswithmembers
● keepclasseswithmembernames
以上是混淆时,经常使用的混淆命令,其中一部分在上一篇介绍过,这里只说明另一部分命令:
这里写图片描述

保持元素不参与混淆的规则

[保持命令] [类] {
[成员]
}
“类”代表类相关的限定条件,它将最终定位到某些符合该限定条件的类,它可以使用:
● 具体的类
● 访问修饰符(public、protected、private)
● 通配符*,匹配任意长度字符,但不含包名分隔符(.)
● 通配符**,匹配任意长度字符,并且包含包名分隔符(.)
● extends,即可以指定类的基类
● implement,匹配实现了某接口的类
● $,内部类

“成员”代表类成员相关的限定条件,它将最终定位到某些符合该限定条件的类成员,它可以使用:
● 匹配所有构造器
● 匹配所有域
● 匹配所有方法
● 通配符*,匹配任意长度字符,但不含包名分隔符(.)
● 通配符**,匹配任意长度字符,并且包含包名分隔符(.)
● 通配符*,匹配任意参数类型
● …,匹配任意长度的任意类型参数。比如void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。
● 访问修饰符(public、protected、private)

例如:需要将com.test包下所有继承Activity的public类及其构造函数都不参与混淆
-keep public class com.test.** extends Android.app.Activity{

}

常用的自定义混淆规则

不混淆某个类
-keep public class com.test.example.Test { *; }

不混淆某个包所有的类
-keep class com.test.* { ; }

不混淆某个类的子类
-keep public class * extends com.test.example.Test { *; }

不混淆所有类名中包含了“model”的类及其成员
-keep public class .model. {*;}

不混淆某个接口的实现
-keep class * implements com.test.example.TestInterface { *; }

不混淆某个类的构造方法
-keepclassmembers class com.test.example.Test {
public ();
}

不混淆某个类的特定的方法
-keepclassmembers class com.test.example.Test {
public void test(java.lang.String);
}

自定义资源保持规则

1.keep.xml
用shrinkResources true 开启资源压缩后,所有未被使用的资源默认被移除,假如你需要定义哪些资源必须被保留,在res/raw/ 路径下创建一个xml文件,例如keep.xml。

通过一些属性的设置可以实现定义资源保持的需求,可配置的属性有:
● tools:keep 定义哪些资源需要被保留(资源之间用“,”隔开)
● tools:discard 定义哪些资源需要被移除(资源之间用“,”隔开)
● tools:shrinkMode 开启严格模式

当代码中通过Resources.getIdentifier()用动态的字符串来获取并使用资源时,普通的资源引用检查就可能会有问题,例如,如下代码会导致所有以“img_”开头的资源都被标记为已使用。
String name = String.format(“img_%1d”, angle + 1);
res = getResources().getIdentifier(name, “drawable”, getPackageName());

这时,我们可以设置 tools:shrinkMode 为 strict 来开启严格模式,使只有确实被使用的资源被保留。
以上就是自定义资源保持规则相关的配置,举个例子:

Android混淆原则

反射用到的类不混淆
JNI方法不混淆
AndroidMainfest中的类不混淆,四大组件和Application的子类和Framework层下所有的类默认不混淆
Parcelable的子类和Creator静态成员变量不混淆
使用GSON、fastjson等框架时,所写的JSON对象类不混淆
使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则
有用到WEBView的JS调用也需要保证写的接口方法不混淆

如果加入一些自己的混淆规则 只需要在 proguard-rules.pro 中文件加入自己的混淆规则:
1. 代码中使用了反射,如一些ORM框架的使用,需要保证类名 方法不变, 不然混淆后, 就反射不了;
2. 使用GSON、fastjson等JSON解析框架所生成的对象类,生成的bean实体对象,内部大多是通过反射来生成, 不能混淆;
3. 引用了第三方开源框架或继承第三方SDK,如开源的okhttp网络访问框架,百度定位SDK等在这些第三库的文档中 一班会给出 相应的 混淆规则, 复制过来即可;
5. 继承了Serializable接口的类在反序列画的时候, 需要正确的类名等, 在Android 中大多是实现 Parcelable来序列化的;
其实自己加入的规则 一般都是说,某某类 不混淆等等。

如果用到了反射需要加入 :
-keepattributes Signature
-keepattributes EnclosingMethod

有用到WEBView的JS调用接口,需加入如下规则:
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
-keep class com.xxx.xxx.* { ; }//保持WEB接口不被混淆 此处xxx.xxx是自己接口的包名

移除一些log代码:
-assumenosideeffects class android.util.Log {
public static * v(…);
public static * i(…);
public static * d(…);
public static * w(…);
public static * e(…);
}

其他注意事项

1,如何确保混淆不会对项目产生影响:
测试工作要基于混淆包进行,才能尽早发现问题;
每天开发团队的冒烟测试,也要基于混淆包;
发版前,重点的功能和模块要额外的测试,包括推送,分享,打赏。

2,打包时忽略警告:
当导出包的时候,发现很多could not reference class之类的warning信息,如果确认App在运行中和那些引用没有什么关系,可以添加-dontwarn 标签,就不会提示这些警告信息了。

3,对于自定义类库的混淆处理:
比如我们引用了一个叫做AndroidLib的类库,我们需要对Lib也进行混淆,然后在主项目的混淆文件中保留AndroidLib中的类和类的成员。

参考:http://mp.weixin.qq.com/s?__biz=MzI4NTQ2OTI4MA==&mid=2247483651&idx=1&sn=85f0d6c6a0f6c4f2ece97429f423c51c&chksm=ebeafe0cdc9d771a31344d0d6861e3b864bfe36d46652770aa522631eb0115a754e1be579d3b#rd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值