前言
記錄一下關(guān)于 Android 中關(guān)于混淆配置文件的生效規(guī)則、混淆規(guī)則的細(xì)節(jié)拍棕、build 產(chǎn)物中和混淆相關(guān)的內(nèi)容及其作用。
混淆配置生效規(guī)則
現(xiàn)在的 Android 項(xiàng)目一般由一個(gè)主 app module
勺良,n 個(gè)子 lib module
共同組成绰播。 app module
通過(guò) dependencies 閉包依賴這些子 module ,或者是將這些子 module 上傳到中央倉(cāng)庫(kù)之后進(jìn)行依賴郑气。
if (source_code.toBoolean()) {
implementation project(path: ':thirdlib')
} else {
implementation 'com.engineer.third:thirdlib:1.0.0'
}
implementation project(path: ':compose')
implementation project(path: ':common')
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2'
...
比如對(duì)于下圖中的幾個(gè)子 module
可以通過(guò) project(path: 'xxx')
的方式依賴幅垮,也可以將這個(gè)本地 module 上傳到中央倉(cāng)庫(kù)之后通過(guò) group_id:artifact_id:version
的方式依賴。
那么這兩種方式依賴由哪些差異呢尾组?
- 遠(yuǎn)程依賴會(huì)比直接在本地依賴節(jié)省一些編譯時(shí)間 (當(dāng)然這不包括下載依賴本身耗費(fèi)的時(shí)間)忙芒,畢竟可以省去編譯源碼及資源的時(shí)間。
- 對(duì)于混淆來(lái)說(shuō)讳侨,這兩種依賴方式混淆配置規(guī)則的生效是有些差異的呵萨。這里的差異是說(shuō)混淆配置文件的差異,而不是說(shuō)具體的一條混淆配置語(yǔ)法會(huì)有差異 跨跨。
下面具體來(lái)說(shuō)一下這個(gè)差異潮峦。關(guān)于混淆配置囱皿,除了各個(gè) moudle 下我們非常熟悉的肉眼可見 proguard-rules.pro
之外,其實(shí)還有別的混淆配置忱嘹,最終會(huì)合并在一起生效嘱腥。
說(shuō)到各個(gè) module 的配置文件合并,大家一定會(huì)想到 AndroidManifest.xml 拘悦。最終打包使用的 AndroidManifest.xml 的內(nèi)容齿兔,就是各個(gè)子 module 和主 module merge 后的結(jié)果。
需要注意的是础米,Android 打包過(guò)程并不會(huì)主動(dòng)合并本地 module 中的 proguard-rules.pro
文件 分苇。注意,這里說(shuō)的是本地 module .
也就是說(shuō)像 common/thirdlib/compose 這類直接在本地依賴的 module, 其內(nèi)部的 proguard-rules.pro
并不會(huì)直接生效屁桑。 而通過(guò) implementation group_id:artifact_id:version
依賴的遠(yuǎn)程 module ,如果其內(nèi)部有配置 proguard 規(guī)則医寿,就會(huì) merge 到最終的混淆配置中。上一篇 發(fā)布 Android Lib 到 Maven 解惑 中我們提到蘑斧, library
通過(guò) gradle 任務(wù)發(fā)布到中央倉(cāng)庫(kù)的時(shí)候靖秩,會(huì)基于本地 consumer-rules.pro
生成最終的 proguard.txt
文件一并打包到 aar 文件中;這里 merge 的就是這個(gè)自動(dòng)生成的 proguard.txt
乌叶。而最終的混淆配置規(guī)則疊加到一起之后盆偿,在 app/build/outputs/mapping/huaweiLocalRelease/configuration.txt
這個(gè)文件里。
這個(gè)文件是有規(guī)則的准浴,會(huì)按照段落列出編譯過(guò)招中所涉及的模塊事扭。
001:# The proguard configuration file for the following section is D:\workspace\MinApp\app\build\intermediates\default_proguard_files\global\proguard-android-optimize.txt-7.2.1
121:# The proguard configuration file for the following section is D:\workspace\MinApp\app\proguard-rules.pro
182:# The proguard configuration file for the following section is D:\workspace\MinApp\app\build\intermediates\aapt_proguard_file\huaweiLocalRelease\aapt_rules.txt
392:# The proguard configuration file for the following section is D:\workspace\MinApp\common\build\intermediates\consumer_proguard_dir\release\lib0\proguard.txt
395:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\89e35bb901a511dc73379ee56d9a96fb\transformed\navigation-ui-2.3.5\proguard.txt
416:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\ed14b9608e236c3cb341584bd1991f2a\transformed\material-1.5.0\proguard.txt
465:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\38b91e3dad918eabe8ced61c0f881bef\transformed\jetified-stetho-1.6.0\proguard.txt
470:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\380c0daab5f38fa92451c63d6b7f2468\transformed\preference-1.1.1\proguard.txt
494:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\a00816a85507c4640738406281464e4f\transformed\appcompat-1.4.1\proguard.txt
519:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\19a9b30d1e238c7cf954868475b2d87a\transformed\navigation-common-ktx-2.3.5\proguard.txt
541:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\bc1e654ac594a8eec67d83a310d595cd\transformed\rules\lib\META-INF\com.android.tools\r8-from-1.6.0\kotlin-reflect.pro
559:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\822d22c7ed69ccdf4d90c18a483e72c5\transformed\rules\lib\META-INF\com.android.tools\r8-from-1.6.0\coroutines.pro
585:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\555542c94d89a20ac01618f64dfcfed2\transformed\rules\lib\META-INF\proguard\coroutines.pro
608:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\a830f069563364388aaf53b586352be8\transformed\jetified-glide-4.13.1\proguard.txt
625:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\9ce146a7d8708a759f2821d06606c176\transformed\jetified-flexbox-1.0.0\proguard.txt
647:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\003c1e88ccf7eabdb17daba177d5544b\transformed\jetified-hilt-lifecycle-viewmodel-1.0.0-alpha03\proguard.txt
654:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\2675f8213875fddbbb3d30c803c00c9c\transformed\jetified-hilt-android-2.40.1\proguard.txt
665:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\3368f9a73434dea0d4e52626ffd9a8c9\transformed\fragment-1.3.6\proguard.txt
687:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\58278e1b3a97715913034b7b81fae8cb\transformed\jetified-lifecycle-viewmodel-savedstate-2.3.1\proguard.txt
697:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\cb4d77137f22248d78cd200f94d17fc4\transformed\jetified-savedstate-1.1.0\proguard.txt
717:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\6a6fcb77b4395418002e332cd9738bfb\transformed\work-runtime-2.7.0\proguard.txt
728:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\4ab9d68c51a5e06d113a80174817d2cc\transformed\media-1.0.0\proguard.txt
753:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\5599788d3c018cf9be3c21d9a4ff4718\transformed\coordinatorlayout-1.1.0\proguard.txt
778:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\0e108ece111c1c104d1543d98f952017\transformed\vectordrawable-animated-1.1.0\proguard.txt
800:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\19c137c4f40e8110221a03964c21b354\transformed\recyclerview-1.1.0\proguard.txt
827:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\9eb9006bf5796c20208d89f414c860f8\transformed\transition-1.3.0\proguard.txt
848:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\848cc86aa556453b7ae2d77cf1ed69f7\transformed\core-1.7.0\proguard.txt
867:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\c269ff43c6850351c92a4f3de7a5d26d\transformed\jetified-lifecycle-process-2.4.0\proguard.txt
871:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\f082dcda3ea45d057bb4fd056c4b3864\transformed\lifecycle-runtime-2.4.0\proguard.txt
896:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\c78621e75bc17f9e3a8dc4279fe51aed\transformed\rules\lib\META-INF\proguard\retrofit2.pro
928:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\9dd79968324ef9619ccee991ab21aa68\transformed\rules\lib\META-INF\proguard\rxjava2.pro
931:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\9eef9e5128bbcd6232ee9a89f4c5bf00\transformed\lifecycle-viewmodel-2.3.1\proguard.txt
941:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\5875adda5cf6fa792736faf48738cf7c\transformed\jetified-startup-runtime-1.0.0\proguard.txt
952:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\e06b693ee9109a0e8f8d0949e74720e0\transformed\room-runtime-2.4.0\proguard.txt
957:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\6008298b41480f69c56a08890c83e302\transformed\versionedparcelable-1.1.1\proguard.txt
964:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\2810bf2a83f304a3ff02e4019efe065f\transformed\rules\lib\META-INF\proguard\androidx-annotations.pro
985:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\6dc53357fb30238e16dbc902967a8aab\transformed\jetified-annotation-experimental-1.1.0\proguard.txt
1011:# The proguard configuration file for the following section is D:\Android\.gradle\caches\transforms-3\4233f8c9725e3a6760c0e0e606e43b29\transformed\rules\lib\META-INF\proguard\okhttp3.pro
1025:# The proguard configuration file for the following section is <unknown>
可以看到,除了我們熟悉的 app/proguard-rules.pro 之外乐横,其實(shí)還使用了其他 module 的 xxx.pro 文件求橄。當(dāng)然,這里有些文件葡公,可能沒(méi)有配置任何內(nèi)容罐农,只是一個(gè)默認(rèn)的配置,就像 app/proguard-rules.pro 剛創(chuàng)建時(shí)候的樣子催什,有興趣的話可以打開文件查看涵亏。
在這個(gè)最終的混淆配置規(guī)則里還有一些值得我們注意的地方。
- proguard-android-optimize.txt-7.2.1
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
# the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
# will be ignored by new version of the Android plugin for Gradle.
也就是說(shuō)從 AGP 2.2 開始蒲凶,在編譯階段會(huì)使用當(dāng)前 AGP 插件所攜帶的混淆規(guī)則气筋,而不在使用本地 Android SDK/tools/proguard/ 目錄下的混淆配置了。 這個(gè)混淆配置文件里規(guī)則都非常通用的旋圆,比如對(duì)于 enum , Keep 注解宠默,webview Interface 等等之類的規(guī)則。 這就意味著 AGP 插件的升級(jí)有可能會(huì)影響到混淆灵巧,如果某個(gè) AGP 版本所攜帶的混淆規(guī)則發(fā)了一些變化的話搀矫。
- aapt_rules.txt
aapt 顧名思義抹沪,就是在執(zhí)行 AAPT 階段生成的混淆規(guī)則,可以看到里面都是基于 Android 應(yīng)用層源碼的一些配置瓤球。會(huì)根據(jù)代碼中的資源文件融欧、布局文件等內(nèi)容生成相應(yīng)的規(guī)則。比如會(huì)基于 AndroidManifest.xml 中聲明的四大組件冰垄,保留相應(yīng)的 Activity蹬癌、Service 等類的構(gòu)造函數(shù),一些自定義 View 的構(gòu)造函數(shù)等虹茶。
- META-INF\proguard\okhttp3.pro
這類混淆規(guī)則其實(shí)是 xxx.jar
文件內(nèi)部的混淆規(guī)則。Android 開發(fā)中非常實(shí)用的 okhttp隅要、RxJava蝴罪、Retrofit
等這些純 Java/Kotlin 代碼的 module 打包之后上傳到中央倉(cāng)庫(kù)的就是 jar 文件,而不是 aar (畢竟不涉及到 UI,因此也不會(huì)有資源文件了)步清。
對(duì)于 java-library
類型的 module要门, 通過(guò)上述配置,最終打包的 jar 文件中將包含這個(gè) thirdlib.pro
混淆配置文件廓啊。
剩下的就是一些我們常用的類庫(kù)自身攜帶的混淆規(guī)則了欢搜,可以看到這些 aar
類型的庫(kù)其混淆配置文件都是 proguard.txt 。
從這里我們可以看到谴轮,AGP 已經(jīng)非常完善了炒瘟,在打包過(guò)程中會(huì)在基于實(shí)際代碼自動(dòng)生成相應(yīng)的混淆規(guī)則,尤其是關(guān)于 Android 自身類及組件的配置第步。平時(shí)在網(wǎng)上看到的各種混淆配置疮装,沒(méi)必要非得對(duì)著里面的內(nèi)容一條一條的進(jìn)行配置,一些非痴扯迹基礎(chǔ)且共用的混淆規(guī)則都是默認(rèn)的廓推。我們實(shí)際需要關(guān)心的還是自身業(yè)務(wù)相關(guān)的混淆規(guī)則,比如涉及 Json 序列化操作的 Model 類的翩隧,以及自己寫的涉及反射操作的類樊展。
那么子 moudle 直接在本地依賴的情況下,混淆配置是如何生效的呢堆生?
子 module 的生效規(guī)則
這里我們可以重點(diǎn)關(guān)注一下 392:# The proguard configuration file for the following section is D:\workspace\MinApp\common\build\intermediates\consumer_proguard_dir\release\lib0\proguard.txt
從路徑就可以猜出來(lái)了专缠,這里的 lib0 就是本地依賴的 common
module 。
這部分在 configuration.txt 中是這樣的顽频。
# The proguard configuration file for the following section is D:\workspace\MinApp\common\build\intermediates\consumer_proguard_dir\release\lib0\proguard.txt
-keep class com.engineer.common.utils.AndroidFileUtils {*;}
# End of content from D:\workspace\MinApp\common\build\intermediates\consumer_proguard_dir\release\lib0\proguard.txt
這部分就是子 module 的混淆配置藤肢。子 module 混淆配置生效有兩種方式,而這兩種方式都依賴 consumerProguardFiles
這個(gè)屬性糯景。
直接使用 consumer-rules.pro
直接在子 module 的 consumer-rules.pro
中配置要混淆的規(guī)則嘁圈。然后在 build.gradle 中通過(guò)默認(rèn)的配置生效
defaultConfig {
minSdk ext.minSdkVersion
targetSdk ext.targetSdkVersion
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
子 module 創(chuàng)建的時(shí)候省骂,會(huì)默認(rèn)在 defaultConfig 閉包中添加 consumerProguardFiles 這個(gè)配置,因此只要在 consumer-rules.pro
中配置了混淆規(guī)則最住,就會(huì)生效钞澳。
使用 proguard-rules.pro
如果你不習(xí)慣使用 consumer-rules.pro
的話,也可以使用 proguard-rules.pro
涨缚,直接配置一下就可以了轧粟。
buildTypes {
release {
minifyEnabled false
consumerProguardFiles "proguard-rules.pro"
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
這兩種方式配置的內(nèi)容,最終都會(huì)生效脓魏。再次謹(jǐn)記兰吟,混淆規(guī)則是疊加生效的,并不存在什么先后順序茂翔。打包過(guò)程中只要找到了可用的配置文件混蔼,就會(huì)照單全收
混淆產(chǎn)物
說(shuō)完了混淆配置生效的規(guī)則,可以一并再看一下混淆的產(chǎn)物珊燎。打包完成后惭嚣,會(huì)在 app/build/outputs/mapping/{flavor}/
目錄下生成一些混淆相關(guān)的文件。
文件名 | 作用 |
---|---|
configuration.txt | 所有混淆配置的匯總 |
mapping.txt | 原始與混淆過(guò)的類悔政、方法晚吞、字段名稱間的轉(zhuǎn)換 |
resources.txt | 資源優(yōu)化記錄文件,哪些資源引用了其他資源谋国,哪些資源在使用槽地,哪些資源被移除 |
seeds.txt | 未進(jìn)行混淆的類與成員 |
usage.txt | APK中移除的代碼 |
通過(guò)這些文件,我們就可以看到一次打包過(guò)程中烹卒,混淆具體做了哪些事情闷盔。比較常用的是 mapping.txt 文件,當(dāng)混淆過(guò)后的包出現(xiàn)問(wèn)題時(shí)旅急,通過(guò) stacktrace 定位問(wèn)題的時(shí)候逢勾,由于代碼被混淆會(huì)無(wú)法識(shí)別,這時(shí)候就是通過(guò) mappting.txt 文件解混淆藐吮。這里使用過(guò) bugly 的同學(xué)應(yīng)該很熟悉了溺拱。線上代碼出現(xiàn)問(wèn)題,上傳 mapping 文件就可以快速定位到出現(xiàn)問(wèn)題的具體代碼了谣辞。
通過(guò) seeds.txt 也可以看到哪些文件沒(méi)有被混淆迫摔,內(nèi)容是否符合預(yù)期。
上面混淆配置生效規(guī)則里提到了泥从,打包過(guò)程中會(huì)綜合各個(gè) module 的混淆配置文件句占。因此,有時(shí)候我們會(huì)發(fā)現(xiàn)躯嫉,自己明明沒(méi)有配置某些類的 keep ,但是這些類依然沒(méi)有被混淆纱烘,這時(shí)候可能就是由于項(xiàng)目本身依賴的 module 的混淆規(guī)則生效了杨拐。 比如 configuration.txt 中 Android fragment 包的這條規(guī)則
# The proguard configuration file for the following section is /Users/rookie/.gradle/caches/transforms-3/3368f9a73434dea0d4e52626ffd9a8c9/transformed/fragment-1.3.6/proguard.txt
# The default FragmentFactory creates Fragment instances using reflection
-if public class ** extends androidx.fragment.app.Fragment
-keepclasseswithmembers,allowobfuscation public class <1> {
public <init>();
}
# End of content from /Users/rookie/.gradle/caches/transforms-3/3368f9a73434dea0d4e52626ffd9a8c9/transformed/fragment-1.3.6/proguard.txt
所有繼承自 androidx.fragment.app.Fragment 的類都會(huì)隨著其構(gòu)造方法的一起被 keep 。這樣最終混淆結(jié)果中就會(huì)有很多的業(yè)務(wù)相關(guān)的 XXXFragment 類無(wú)法被混淆擂啥。至于原因哄陶,上面的注釋解釋的很清楚了,需要通過(guò)反射創(chuàng)建 Fragment 的實(shí)例哺壶。
所以屋吨,在混淆過(guò)程中,如果發(fā)現(xiàn)一些沒(méi)有類沒(méi)有被混淆山宾,不妨在 configuration.txt
中找找原因至扰。
嚴(yán)格來(lái)說(shuō),resources.txt 是由于配置了 shrinkResources true
對(duì)無(wú)效資源文件進(jìn)行移除操作后產(chǎn)生的結(jié)果资锰,不算是混淆渊胸,但是這里可以理解為混淆過(guò)程
混淆規(guī)則
混淆規(guī)則本質(zhì)上非常靈活,很難用一句話概括清楚台妆。這里引用郭神的Android安全攻防戰(zhàn),反編譯與混淆技術(shù)完全解析(下) 中的表述 胖翰,感覺(jué)比較清晰接剩。
keep 關(guān)鍵字規(guī)則
關(guān)鍵字 | 描述 |
---|---|
keep | 保留類和類中的成員,防止它們被混淆或移除萨咳。 |
keepnames | 保留類和類中的成員懊缺,防止它們被混淆,但當(dāng)成員沒(méi)有被引用時(shí)會(huì)被移除培他。 |
keepclassmembers | 只保留類中的成員鹃两,防止它們被混淆或移除。 |
keepclassmembernames | 只保留類中的成員舀凛,防止它們被混淆俊扳,但當(dāng)成員沒(méi)有被引用時(shí)會(huì)被移除。 |
keepclasseswithmembers | 保留類和類中的成員猛遍,防止它們被混淆或移除馋记,前提是指名的類中的成員必須存在,如果不存在則還是會(huì)混淆懊烤。 |
keepclasseswithmembernames | 保留類和類中的成員梯醒,防止它們被混淆,但當(dāng)成員沒(méi)有被引用時(shí)會(huì)被移除腌紧,前提是指名的類中的成員必須存在茸习,如果不存在則還是會(huì)混淆。 |
通配符規(guī)則
通配符 | 描述 |
---|---|
<field> |
匹配類中的所有字段 |
<method> |
匹配類中的所有方法 |
<init> |
匹配類中的所有構(gòu)造函數(shù) |
* |
匹配任意長(zhǎng)度字符壁肋,但不含包名分隔符(.)号胚。比如說(shuō)我們的完整類名是com.example.test.MyActivity籽慢,使用com.,或者com.exmaple.都是無(wú)法匹配的涕刚,因?yàn)?em>無(wú)法匹配包名中的分隔符嗡综,正確的匹配方式是com.exmaple..,或者com.exmaple.test.杜漠,這些都是可以的极景。但如果你不寫任何其它內(nèi)容,只有一個(gè)*驾茴,那就表示匹配所有的東西盼樟。 |
** |
匹配任意長(zhǎng)度字符,并且包含包名分隔符(.)锈至。比如proguard-android.txt中使用的-dontwarn android.support.**就可以匹配android.support包下的所有內(nèi)容晨缴,包括任意長(zhǎng)度的子包。 |
*** | 匹配任意參數(shù)類型峡捡。比如void set()就能匹配任意傳入的參數(shù)類型击碗,* get*()就能匹配任意返回值的類型。 |
… |
匹配任意長(zhǎng)度的任意類型參數(shù)们拙。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)這些方法稍途。 |
網(wǎng)上大部分文章提到的混淆配置語(yǔ)法都大同小異,都是從正面出發(fā)砚婆,這樣有時(shí)候其實(shí)是不太靈活的械拍。比如在某些場(chǎng)景下我們需要保留所有實(shí)現(xiàn)了 Serializable
接口的類,因?yàn)檫@些類涉及到序列化操作装盯。
-keep class * implements java.io.Serializable {*;}
這條規(guī)則本身沒(méi)問(wèn)題坷虑,但是其實(shí)這個(gè)規(guī)則的范圍是很大的。因?yàn)槲覀兂S玫?enum 的具體實(shí)現(xiàn) Enum 類
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable { ....}
也是實(shí)現(xiàn)了 Serializable
接口的埂奈。因此會(huì)導(dǎo)致所有的 enum 類型無(wú)法被混淆迄损。實(shí)際上 Java 集合框架也有很多類實(shí)現(xiàn)了這個(gè)接口。雖然 Android 官方不建議使用枚舉挥转,但是現(xiàn)實(shí)中使用的還是挺多的海蔽,比如 glide 。這樣就會(huì)導(dǎo)致原本可以被混淆的類受到牽連绑谣。
那么可以避免這種情況嗎党窜?其實(shí)是有辦法的,細(xì)心的話你也許已經(jīng)發(fā)現(xiàn)了借宵,在上面 FragmentFactory
的混淆配置語(yǔ)法里有條件判斷的邏輯幌衣。
# The default FragmentFactory creates Fragment instances using reflection
-if public class ** extends androidx.fragment.app.Fragment
-keepclasseswithmembers,allowobfuscation public class <1> {
public <init>();
}
看到這里的 if 你是不是有點(diǎn)想法了呢?強(qiáng)烈建議在需要配置混淆規(guī)則的時(shí)候多參考一下 configuration.txt
中一些官方庫(kù)的配置規(guī)則,也許會(huì)讓你打開一扇新的打門豁护。
混淆認(rèn)知
混淆配置規(guī)則看起來(lái)簡(jiǎn)單哼凯,但其實(shí)結(jié)合實(shí)際場(chǎng)景會(huì)變得有些復(fù)雜,尤其是代碼包含內(nèi)部類楚里,匿名內(nèi)部断部,靜態(tài)內(nèi)部類等等不同場(chǎng)景下。這些具體的規(guī)律還是需要結(jié)合實(shí)際場(chǎng)景通過(guò)不斷的驗(yàn)證班缎。 關(guān)于代碼混淆蝴光,最好的學(xué)習(xí)方法就是自己通過(guò)寫代碼,組合各類配置不斷驗(yàn)證达址。打包后可以用 jadx-gui 查看混淆的 apk 文件蔑祟。
最后再補(bǔ)充一個(gè)進(jìn)行混淆配置驗(yàn)證時(shí)的小技巧。
android {
//...
lint {
checkReleaseBuilds false
}
}
直接在 app/build.gradle android 閉包下配置關(guān)閉 releaseBuild 時(shí)的 lint 檢查沉唠。畢竟混淆規(guī)則的修改不會(huì)影響代碼本身疆虚,因此可以通過(guò)跳過(guò)檢測(cè),節(jié)省編譯時(shí)間满葛。畢竟這個(gè) lint 檢查的耗時(shí)還是很可觀的径簿。這樣就可以避免每次打包時(shí)的等待了。 有些時(shí)候臨時(shí)打 release 包驗(yàn)證一些問(wèn)題的時(shí)候嘀韧,也可以臨時(shí)加上這個(gè)配置關(guān)閉檢測(cè)牍帚。
參考
- 補(bǔ)齊Android技能樹 - 從害怕到玩轉(zhuǎn)Android代碼混淆
- Android安全攻防戰(zhàn),反編譯與混淆技術(shù)完全解析(下)
- Android代碼混淆及ProGuard手冊(cè)
- Android開發(fā):請(qǐng)你吃一頓史上最全的Android混淆大餐
- 混淆的另一重境界
作者:IAM四十二
鏈接:https://juejin.cn/post/7148456353332215838