Android 混淆規(guī)則是如何生效的畦幢?

前言

記錄一下關(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è)牍帚。

參考

作者:IAM四十二
鏈接:https://juejin.cn/post/7148456353332215838

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乳蛾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鄙币,更是在濱河造成了極大的恐慌肃叶,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件十嘿,死亡現(xiàn)場(chǎng)離奇詭異因惭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绩衷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門蹦魔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人咳燕,你說(shuō)我怎么就攤上這事勿决。” “怎么了招盲?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵低缩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)咆繁,這世上最難降的妖魔是什么讳推? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮玩般,結(jié)果婚禮上银觅,老公的妹妹穿的比我還像新娘。我一直安慰自己坏为,他們只是感情好究驴,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著久脯,像睡著了一般纳胧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帘撰,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天跑慕,我揣著相機(jī)與錄音,去河邊找鬼摧找。 笑死核行,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蹬耘。 我是一名探鬼主播芝雪,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼综苔!你這毒婦竟也來(lái)了惩系?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤如筛,失蹤者是張志新(化名)和其女友劉穎堡牡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杨刨,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晤柄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妖胀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芥颈。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赚抡,靈堂內(nèi)的尸體忽然破棺而出爬坑,到底是詐尸還是另有隱情,我是刑警寧澤涂臣,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布妇垢,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏闯估。R本人自食惡果不足惜灼舍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涨薪。 院中可真熱鬧骑素,春花似錦、人聲如沸刚夺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)侠姑。三九已至创橄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間莽红,已是汗流浹背妥畏。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留安吁,地道東北人醉蚁。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鬼店,于是被迫代替她去往敵國(guó)和親网棍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容