在我2017年的文章【我的Android进阶之旅】Android 混淆文件资源分类整理中,我已经提及过。
之前将所有的混淆都配置在一个
proguard-rules.pro
这个Android Studio新建项目时自动生成的文件里面,而随着项目功能迭代越来越多,代码量越来越多,引用的第二方库、第三方库都越来越多,导致proguard-rules.pro
越来越臃肿,而且随着开发人员增多导致proguard-rules.pro
文件里面的配置越来越混乱。
一、拆分proguard-rules.pro
混淆文件
因此今天我将
proguard-rules.pro
混淆文件进行拆分整理,大概拆分为以下4个文件:第三方混淆文件、第二份混淆文件、系统默认混淆文件、module单独混淆文件 。
如上图所示,四个文件分别为 'proguard-system-common.pro'
, 'proguard-module.pro'
, 'proguard-second-party.pro'
, 'proguard-third-party.pro'
二、配置混淆时候 proguardFiles 所引用的混淆文件
2.1 常规写法
原来的混淆文件配置代码如下:
//混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro',
改为下面的将四个混淆文件都加入到混淆配置文件列表中
//混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-system-common.pro', 'proguard-module.pro', 'proguard-second-party.pro', 'proguard-third-party.pro'
如下图所示:
2.2 、扩展写法
如果上面那种分开几个文件的写法太复杂,并且以后如果拆分的越来越系,比如每个第三方都拆分一个文件,如下所示,那么可以把几个文件都丢在一个目录下,然后遍历目录即可。
如上图所示
proguardFiles file('../proguard').listFiles().toList().toArray()
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
将所有分好类的混淆文件,放到proguard目录中,然后遍历该目录。
比如之前的build.gradle 的配置 改成下面所示
//混淆文件
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-system-common.pro', 'proguard-module.pro', 'proguard-second-party.pro', 'proguard-third-party.pro'
proguardFiles file('../proguard').listFiles().toList().toArray()
proguardFiles getDefaultProguardFile('proguard-android.txt')
三、拆分更小粒度
至此,我们将一个大一统的混淆文件,拆分成了四个混淆文件。
但是随着项目组件化拆分业务之后,已经将原本的一个工程拆分出20来个小的组件。还是将所有的混淆配置都放在这四个混淆配置里面不合适。
因此,秉承着 单一职责原则(SRP:Single responsibility principle) 的设计原则,我觉得有必要对着四个混淆文件再次进行拆分。
3.1 拆分 第三方混淆文件 proguard-third-party.pro
如下图所示: 新建一个proguard目录用于存放拆分的pro混淆文件。
proguard/third 目录 则用于存放拆分的第三方混淆文件
所有的第三方混淆文件,安装不同的第三方库一个一个的拆分。
3.2 拆分 第二方混淆文件 proguard-second-party.pro
3.3 拆分 项目模块的混淆文件 proguard-module.pro
由于之前没组件化之前,项目只有一个模块,所以全部混淆文件都配置在 proguard-module.pro文件中,现在项目拆分了二十多个组件出去,因此应该将 proguard-module.pro文件的内容拆分到各自的组件中去。
然后在每个组件中的build.gradle文件配置各自组件需要配置的混淆内容。
并使用consumerProguardFiles 引用对应的混淆文件
buildTypes {
release {
minifyEnabled true
consumerProguardFiles 'proguard-rules.pro'
}
debug{
minifyEnabled true
consumerProguardFiles 'proguard-rules.pro'
}
}
3.4 引用拆分完后的混淆文件
刚才出了项目模块的混淆文件 proguard-module.pro被拆分到各自的组件中,并使用consumerProguardFiles 引用拆分后的混淆文件了。
但是拆分的第三方混淆文件和第二方混淆文件,我们并没有引用。
我们回到宿主程序的build.gradle文件去引用刚才拆分掉的小颗粒度的混淆文件。
buildTypes {
release {
shrinkResources true
debuggable debuggableRelease
minifyEnabled true
zipAlignEnabled true
//混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
proguardFiles file('../proguard').listFiles().toList().toArray()
proguardFiles file('../proguard/third').listFiles().toList().toArray()
proguardFiles file('../proguard/second').listFiles().toList().toArray()
}
debug {
shrinkResources true //优化未使用的资源文件
debuggable debuggableDebug //是否可以调试
minifyEnabled true //混淆
zipAlignEnabled true //zip优化安装包大小
//混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
proguardFiles file('../proguard').listFiles().toList().toArray()
proguardFiles file('../proguard/third').listFiles().toList().toArray()
proguardFiles file('../proguard/second').listFiles().toList().toArray()
}
}
这样我们就将四个已经拆分的混淆文件,继续拆分成了颗粒度更小的几十个混淆文件。
四、还能更近一步吗?
4.1 第三方混淆文件打包成AAR 引用到项目中即可
有没有发现,一个团队开发不同的Android APP,大部分使用到的第三方库都差不多。难道我们要每开发一个APP都将这堆配置复制粘贴一遍? 当然也是可以的。
但是如果有一个统一的配置直接就可以一行代码引用呢?是否更加happy?答案是可以的!
4.1.1 FreeProGuard 介绍
PS: 某天正好逛到github上有一个类似的实现 https://github.com/Blankj/FreeProGuard
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
下面就是这个FreeProguard库的介绍
buildTypes {
release {
consumerProguardFiles file('.').listFiles(new FilenameFilter() {
@Override
boolean accept(File file, String s) {
return s.endsWith('.pro')
}
})
}
}
About
FreeProGuard 为方便广大 Android 开发者们今后防混淆配置,很久之前便有打算做这个免混淆库了,只是拖到最近才有空来实现该库,该库利用了 consumerProguardFiles
来传递 aar 中的防混淆配置到主工程中,所以依赖了该库后常用的主流三方库便不再需要开发者们手动配置了,当然,有些友善的库已采用了该方式,我也希望更多的开源库使用该方式从而省去开发者配置防混淆,本库已配置了如下防混淆文件(包括库的不同版本):
- AndroidCommon
- AliPay(需防混 jar(-libraryjars libs/alipaySDK-20150602.jar))
- AndFix
- AndroidEventBus
- AndroidUniversalImageLoader
- ARouter
- BaiduMap(需防混 jar(-libraryjars libs/baidumapapi_v2_1_2.jar))
- BaseRecyclerViewAdapterHelper
- Bugly
- ButterKnife
- Dagger
- EventBus
- Fastjson
- Fresco
- GaoDeMap
- Getui
- Glide
- GreenDAO
- Gson
- Ijkplayer
- ImmersionBar
- Guava
- Jackson
- JPush
- KotlinxCoroutines
- LitePal
- Mars
- MiPush
- Nuwa
- OkHttp
- PingPlusPlus
- Realm
- Retrofit
- Retrolambda
- RongCloud
- RxJava
- ShareSDK
- SinaWeiboSDK
- Stetho
- Tencent
- UMeng
- UnionPay
- Volley
- XinGe
- XunFei
- ZXing
How to use
-
首先开启混淆,设置
minifyEnabled true
; -
添加依赖:
implementation "com.blankj:free-proguard:1.0.2"
-
把项目中的实体类加入到
proguard-rules.pro
文件中,一般为-keep class urpackage.xx.bean/entity/model.** { *; }
,或者使用@Keep
注解这些实体类; -
把项目中需要防混淆的 jar 加入到
proguard-rules.pro
文件中,比如支付宝 SDK 的-libraryjars libs/alipaySDK-20150602.jar
,如果要对所有 jar 都防混,那么使用-libraryjars libs
即可; -
把项目中用到的一些不包括在如上列表中的三方库配置到
proguard-rules.pro
文件中,或者提 issue 使其加入到本库中来(小众或者冷门的不予合入哦)。
Profit
- 开启混淆会将代码中的所有变量、函数、类的名称变为简短的英文字母代号(也可自定义),在缺乏相应的函数名和程序注释的情况下,即使被反编译,也将难以阅读,提升应用的安全性;
- 混淆通过分析字节码,去掉冗余代码,再加上缩短了变量、函数、类的名称,可以进一步缩减应用大小,如果想混淆资源文件,可以使用微信的 AndResGuard。
Last but not least
如果该库能为你节省 10 分钟甚至更多的时间,请把它分享给他人来帮助更多的开发者们节省时间,这些时间可以多陪伴家人、多运动、多做自己喜欢的事情,希望开源可以帮助到更多的人,也希望更多的人加入到开源中来。
4.1.2 定制你自己团队的FreeProguard
当然,这里面的第三方库实在太多,而且很多第三方库实际和你团队使用的第三方库不一样。所以我的做法是,经验可以借鉴,但是不用他的库。我自己定义自己的FreeProguard。
参考他的思路,将第三方的混淆配置也打包成一个AAR,然后发布到内部的Maven平台。然后其他的团队开发人员都可以引入这个AAR,即可引入第三方库的混淆配置了。
4.2 第二方库混淆文件移入到第二方库的AAR中去
4.2.1 为什么要在第二方库的AAR中独立配置混淆文件?
尽管第二方库的混淆规则我们已经拆分了, 但是毕竟要添加到自己项目的proguard配置里, 以后如果混淆规则改了, 配置还得同步改, 非常不友好。
因此我们希望别人在使用我们的aar的时候不用像使用jar包一样还要再进行相应的混淆配置。同时为了使每个aar库自己维护自己的混淆配置,不再主工程中统一配置,方便代码的维护和修改。
原则: 谁提供AAR库,谁的AAR库中自带该库需要的混淆配置!
可以参考 博文 生成带混淆配置的aar库 了解一下!
4.2.2 在AAR中独立配置混淆文件的方法
其实方法和上面我们拆分module的混淆文件到各自组件中去一样,需要使用到consumerProguardFiles关键字。
4.2.2.1Android 对aar独立配置自己混淆文件的支持
Android 在构建apk的时候,会把每一个aar中的混淆配置文件读取出来,作为总的混淆配置文件,然后以这个总的混淆配置表对全部的Java代码进行混淆。
因此只要我们的aar中包含了混淆配置文件,那么这个aar在打包到apk的时候,其自带的混淆配置就会对全部的Java代码生效。
因此Android是支持aar独立配置自己混淆文件的,只要aar中包含混淆配置文件即可。
4.2.2.2 gradle 中的将混淆文件打包到aar中的方法
默认情况下,我们使用Android studio 的gradle 打包方式生成的aar文件中是不包含混淆配置的,因此我们需要使用gradle的consumerProguardFiles方法将混淆文件打包到aar中。
如上面拆分module的一样,也是在第二方库的源代码中,使用consumerProguardFiles配置混淆文件
consumerProguardFiles 方法接收打参数是一个文件(混淆文件)的数组,因此我们在使用consumerProguardFiles方法的时候,可以有如下几种写法:
- a、单一的混淆配置文件:
consumerProguardFiles 'proguard.pro'
- b、多个混淆配置文件:
consumerProguardFiles 'proguard-a.pro','proguard-b.pro'
或
consumerProguardFiles fileTree(dir: projectDir, include: 'proguard*')
或者如上面的FreeGuard
buildTypes {
release {
consumerProguardFiles file('.').listFiles(new FilenameFilter() {
@Override
boolean accept(File file, String s) {
return s.endsWith('.pro')
}
})
}
}
4.2.3 consumerProguardFiles方法原理
默认我们打的aar中是没有混淆配置文件的,但是使用consumerProguardFiles方法后我们解压我们的aar会发现其中多了一个proguard.txt文件:
具体映射关系如下所示:
在 aar库/build/intermediates/bundles 目录下 会生成一个 proguard.txt文件
我们可以对比一个源文件和一个生成的文件
- 混淆源文件 proguard-rules.pro
- 生成的proguard.txt文件
打开这个proguard.txt 可以发现 里面的内容和我们写的混淆配置是一样的。
如果consumerProguardFiles 后面传入了多个混淆配置文件,最终生成的aar中也仅仅只有一个proguard.txt文件,多个proguard*文件是内容merge到这个proguard.txt文件中的。
五、总结
- 单一责任原则,将混淆文件尽量拆分成更小颗粒度
- 谁提供谁负责混淆,尽量将内部开发的第二方库的混淆配置,直接在AAR中附带产生,这样使用AAR的人就不需要去再单独配置
- 对于第三方库的混淆文件,可以配置一个AAR库,将所有第三方库的混淆规则都配置进去,方便团队成员使用混淆配置。
- 掌握proguardFiles 和 consumerProguardFiles的区别
六、参考链接
- 【我的Android进阶之旅】Android 混淆文件资源分类整理
- Android aar中增加独立的混淆配置
- 【FreeProguard】
- Android高级混淆和代码保护技术
- 生成带混淆配置的aar库
版权声明:本文为【欧阳鹏】原创,依据 CC BY-SA 4.0 许可证进行授权,欢迎转载,转载请附上出处链接及本声明。【博客地址 http://blog.csdn.net/ouyang_peng】
本文链接:https://ouyangpeng.blog.csdn.net/article/details/106871878
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:https://ouyangpeng.blog.csdn.net/article/details/106731755
☞ 本人QQ: 3024665621
☞ QQ交流群: 123133153
☞ github.com/ouyangpeng
☞ oypcz@foxmail.com
————————————————
版权声明:本文为CSDN博主「欧阳鹏」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://ouyangpeng.blog.csdn.net/article/details/106731755
————————————————
转载:https://blog.csdn.net/qq446282412/article/details/106871878