概述
对于学习Android开发的我们都知道,在发布生产包时需要对项目开启混淆,这样可以避免项目代码暴露在别人面前。而Android Studio在build.gradle文件配置上也非常贴心的提供了开启代码混淆的方式,开发者只要按照官方建议进行配置即可。
android {
buildTypes {
release {
minifyEnabled true //开启混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
...
}
...
proguard-android.txt文件提供了基本的混淆规则,存在Android SDK中,无需修改。而proguard-rules.pro文件,就是提供给开发者添加或修改自定义的混淆规则。可以说我们自定义混淆的全部规则都是在这个文件上进行的。这里我们不会介绍针对具体代码进行混淆。我们考虑的是从项目管理的角度上,如何让该配置文件的效益最大化。
提出问题
为什么要配置文件的效率最大化?
我们提出一个场景,随着项目功能迭代越来越多,代码量越大,引用的第三方库同样越来越多。这样导致的结果就是proguard-rules.pro文件越发臃肿,而且我们修改proguard-rules.pro文件频繁,一不小心就会出现大量的代码冗余。这对于追求极致的工程师来说是不可容忍的。
解决方案(一)
上面问题的根源就是代码耦合度高,修改了一处其他地方也要修改,我们即知道了问题之所在,那就好办了。既然我们在引用第三方库的时候,都需要加上混淆代码,那么我们可以将所有的三方库的混淆代码集中在一处管理就行了。这样我们只需要新加上一个混淆文件来管理这些代码就可以了,该文件专门来管理这些第三方的混淆代码,其他常规的混淆代码还是放在原来的配置文件中。如下:
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro','proguard-third-rules.pro'
如上只要在项目中proguard-rules.pro的同级别目录下,新建proguard-third-rules.pro文件,然后配置第三方混淆代码即可。
解决方案(二)
通过增加混淆文件的方法,来将原来proguard-rules.pro文件的混淆代码进行拆分。这样的确解决了上面单个混淆文件代码臃肿的问题。但是并不是最优解,它还是没有解决代码耦合度高的问题。当子module中代码修改了需要同步修改它的混淆代码时,你还是要去主app的module中寻找混淆文件来修改。所以最好的解决方案是直接在子module中修改自身proguard-rules.pro文件,而不用修改别处代码,而我们也看到在子module中带了proguard-rules.pro文件,这似乎表明aar文件(子module编译后生成的文件)可以自带混淆配置。当我们满心欢喜,如法炮制,配置混淆代码后,如下:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
运行项目,发现竟然报错了,提示类找不到,这说明混淆没有生效。这下懵逼了,既然提供了这个文件,却不让使用。遇到这样的问题,我想着是否还有其他的配置属性可以使用,就从Android Studio的官方网站上BuildType,看到了关于consumerProguardFiles属性的描述ProGuard rule files to be included in the published AAR. 。点进去一看总共四句话:
List consumerProguardFiles
ProGuard rule files to be included in the published AAR.(混淆规则文件被包含在发布的AAR中)
These proguard rule files will then be used by any application project that consumes the AAR (if ProGuard is enabled).(这些混淆规则应用在程序调用该AAR中)
This allows AAR to specify shrinking or obfuscation exclude rules.(允许AAR指定压缩和混淆规则)
This is only valid for Library project. This is ignored in Application project.(只对Library工程有效,在应用程序项目中被忽略。)
这不正是我所期望的结果吗!看到这里,马上开动,修改子module中配置:
buildTypes {
release {
consumerProguardFiles 'proguard-rules.pro'
}
}
再次执行,完美运行!!