Android项目在完工发布时,需要对代码和资源文件进行混淆,目的有两个:
1⃣️减小压缩包的体积
2⃣️防止代码被反编译后恶意利用
Android Apk混淆分两步走:
1⃣️混淆代码
2⃣️混淆资源文件
本人的开发环境为:
Operation System:Mac OS 10.10.5
Android Studio:2.0 Preview 5
Gradle Plugin:2.0.0-alpha3
buildToolsVersion:23.0.2
minSdkVersion:14
compileSdkVersion :23
targetSdkVersion:23
一.混淆代码
1.在build.gradle(Module app)文件中开启混淆器Proguard
buildTypes {
release {
minifyEnabled true //开启混淆
shrinkResources true //去掉未使用的资源文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
这里介绍一下ProGuard,它是AndroidStudio里新的混淆打包工具。它通过重新命名类名、变量名以及方法名等方式达到优化、混淆代码的效果。处理之后的代码代码名称短小且乱序无规律,从而可以达到减小Apk的体积以及加大反编译的难度的目的。
2.通过上面的一步,我们就再次打包之后的Apk的代码就已经被混淆了。如果你觉得这就结束了,那你就太天真了。
事实上,有一些代码我们是不能混淆的,否则会出现各种各样的错误。官网给出了三种可能会发生错误的情况:
1⃣️一个只在AndroidManifest.xml文件中引用的类
2⃣️一个被JNI层函数调用的函数
3⃣️动态调用的类或方法(反射…)
我们可以通过 如下方式指出不想被混淆的代码:
-keep public class <MyClass>
关于不同代码类型的混淆方式,请参考官网的 ProGuard Usage。
一般一个完整的项目里会用到各种各样的开源框架以及第三方类库,也需要给出对应的混淆规则。一般的框架以及类库都会给出对应的混淆规则,拿我最喜欢用的注解框架ButterKnife来说,它的混淆规则如下:
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* ;
}
-keepclasseswithmembernames class * {
@butterknife.* ;
}
如果你的项目里使用了ButterKnife,而且你又想混淆你的代码,那就需要把上面的混淆规则全部加入你的proguard-rules.pro文件中。
注意:ProGuard默认不混淆四大组件(Activity,Service,BroadcastReceiver,ContentProvider)及其子类。
二.混淆资源文件
经过上面的代码混淆,我们已经能够实现代码的混淆。很大程度上减小了Apk的大小,增加了反编译的难度。但是这还不够。如果你把Apk文件直接解压出来,你会看到下面的结果:
可以看到,资源文件都是可以清楚地拿到的,这样就可能很容易就被看懂,甚至被恶意利用。现在我们就要设法把他们的名字都混淆一下,让其他人反编译了也看不懂,从而保护我们的软件不受侵害。
关于资源文件的混淆,这里推荐两个教程,一个是从更改源码的方式入手,一个是从resources.arsc入手。大家可以看一下参考一下:
1⃣️美团Android资源混淆保护实践
2⃣️安装包立减1M–微信Android资源混淆打包工具