在我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
☞ [email protected]
————————————————
版權聲明:本文爲CSDN博主「歐陽鵬」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://ouyangpeng.blog.csdn.net/article/details/106731755
————————————————