Android中配置代码混淆,需要在gradle中配置minifyEnabled为true,然后再混淆的配置文件中加入我们的混淆规则就可以,minifyEnabled开启后会进行代码压缩,混淆,优化
android {
...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Android使用ProGuard作为压缩,优化和混淆个工具,release版本使用Proguard配置如上。
通常shrinkResources会与minifyEnabled配合使用进行资源压缩,shrinkResource的具体实现再android官方插件中。
shrinkResource会移除代码中无用的资源
比如我自己遇到了一个问题,就是shrinkResource将我的一个布局文件中的类名优化成了< x/>,导致线上报错ClassNotFoundException android.view.x
如果需要配置无用的资源不被压缩和处理的话,可以配置白名单:
新建res/raw/keep.xml,文件,文件内容如下:
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
val name = String.format("img_%1d", angle + 1)
val res = resources.getIdentifier(name, "drawable", packageName)
压缩(shrinking):用来减少应用体积,移除未使用的类和成员。
-dontshrink 关闭压缩
优化(Optimization):默认开启,在字节码级别执行优化,让应用运行的更快
-dontoptimize 关闭优化
-optimizationpasses n 表示proguard对代码进行迭代优化的次数,Android一般为5
混淆(Obfuscation):默认开启,增大反编译的难度,使用keep保护的除外,不会进行混淆。
-dontobfuscate 关闭混淆
gradle中配置下面的参数也可以进行相应的优化:
四字节对齐(zipAlignEnabled):开启四字节对齐可以减少应用在运行时的内存消耗
zipAlignEnabled true
移除无用的resource文件:当ProGuard 把部分无用代码移除的时候,
这些代码所引用的资源也会被标记为无用资源,然后系统通过资源压缩功能将它们移除。
需要注意的是目前资源压缩器目前不会移除values/文件夹中定义的资源(例如字符串、尺寸、样式和颜色)开启后,Android构建工具会通过ResourceUsageAnalyzer来检查哪些资源是无用的,当检查到无用的资源时会把该资源替换成预定义的版本。主要是针对.png、.9.png、.xml提供了TINY_PNG、TINY_9PNG、TINY_XML这3个byte数组的预定义版本。
资源压缩工具默认是采用安全压缩模式来运行,可以通过开启严格压缩模式来达到更好的瘦身效果。
shrinkResources true
D8和R8优化:
Android Studio 3.1 或之后的版本 D8 将会被作为默认的 Dex 编译器,dex的体积和性能更优,
Android Studio 3.0 需要主动在 gradle.properties 文件中新增: android.enableD8 = true。R8是Proguard压缩与优化部分的替代品,当我们打开混淆的时候,R8就默认集成到android gradle plugin中了。
-keep class cn.hadcn.test.**
-keep class cn.hadcn.test.*
一个星号表示保持该包下面的类名,子包下面的类名还是会被混淆,两颗星把本包和子包下面的类名都会保持,使用上面的方式,类名不被混淆但是类中的具体方法和变量命名还是会被混淆,如果需要保持类名和里面的方法和变量不被混淆,我们就需要使用下面的方法:
-keep class cn.hadcn.test.* {*;}
在此规则上,可以使用java语法extends,implements等规则:
-keep public class * extends android.app.Activity
上面的规则,避免所有继承activity的public的类被混淆。
keep内部类的时候需要使用$符号,下面的例子保持ScriptFragment内部类JavaScriptInterface中的所有public内容不被混淆。
-keepclassmembers class cc.ninty.chat.ui.fragment.ScriptFragment$JavaScriptInterface {
public *;
}
-keepclassmembers 防止成员被移除或者被重命名
如果只需要把该类下的特定方法保持不被混淆就好,那你就不能用keep方法了,keep方法会保持类名,而需要用keepclassmembers ,如此类名就不会被保持,为了便于对这些规则进行理解,官网给出了以下表格
移除是指在压缩(Shrinking)时是否会被删除。
如何为项目配置混淆规则:
这个人写的挺好的,这里放上他的链接:
https://www.jianshu.com/p/e01f547979bb
ProGuard官网
混淆语法介绍
https://segmentfault.com/a/1190000018742290
混淆基础介绍
https://www.jianshu.com/p/7436a1a32891
D8与R8简单介绍
Android官方教程
项目配置混淆规则