首頁>科技>

AabResGuard 是位元組跳動抖音技術團隊開源的一款針對 .aab 檔案的資源混淆工具。

AabResGuard 於 2019 年六月研發完成,於 2019 年七月底在 Tiktok、Vigo 等多個海外產品上線,為海外產品提供了資源保護和包大小優化的能力。

經過實踐與驗證,AabResGuard 上線後穩定執行,於是團隊將其開源到社群。為了支援更多場景,AabResGuard 提供了 gradle plugin 和可以單獨執行的 jar 包。除此之外,還提供了除資源混淆之外的一些額外特性。

開發背景什麼是 AAB ?

AAB 即 Android App Bundle,是 Google 推出的 APK 動態打包,動態元件化的技術,通過一個 .aab 結尾的 bundle 檔案組裝一個最適合你手機機型的 APK 來為你的裝置安裝。

An Android App Bundle is a new upload format that includes all your app’s compiled code and resources, but defers APK generation and signing to Google Play.

簡介:Android app bundle (https://developer.android.com/guide/app-bundle/)

為什麼要對 AAB 檔案進行資源混淆?

資源混淆的意義: 保護資源和縮減包體積。

經過統計,APK 大小與安裝轉換率之間存在負相關關係。這種轉換率的下降不僅是由於人們只是選擇不安裝,而是由於各種原因安裝未完成。通過統計,APK 大小約為 10MB 的應用程式的下載完成率將比 APK 大小為 100MB 的應用程式高約 30%(資料來源於 Google play internal data)。

受 Google play 政策的影響,2019 年八月底 Google play 上的應用必須包含 64 位 so 庫,這一政策無疑會對包大小造成爆炸性增長,我們最終決定選用 Android app bundle 方案。

上了 Android app bundle 方案後,我們通過 AAB 匯出了一份 APK 檔案進行包大小的對比,結果發現,包的體積變得更大了,其中的差異主要集中在資源上。

由於 .aab 和 .apk 檔案結構的差異,APK 的資源混淆方案是不適用於 AAB 的。

這部分資源混淆的收益我們不能放棄,於是產出了一份針對 .aab 檔案的資源混淆工具 AabResGuard。

收益

以下資料為 AabResGuard 在 tiktok-9.4.0 版本上的收益,由於每個應用對資源的優化程度不同,所以該資料在不同的應用上的優化不同,以實際資料為準。

AAB 檔案實際上只是一種壓縮包的格式(只用於上傳 Google play store),終端使用者下載的時候會通過使用者手機機型配置的不同,生成一個最適配該配置的 APK,使用者最終安裝和下載的是 APK 檔案。

不同手機的配置不同,所以收益體現不同,上表為(sdk16/arm64/480)的手機配置,由於 Google play store 對包體積會有二次壓縮,所以實際的收益有所減少,具體線上資料的收益請參考 APK download size 的收益。

原理介紹AAB 和 APK 檔案結構的差異

*.aab 和 *.apk 檔案的結構對比如下圖所示:

從圖中可以看出,*.aab 和 *.apk 檔案結構明顯不同,*.aab 檔案中的資源索引檔案為 resources.pb,而 *.apk 檔案中的資源索引檔案為 resources.arsc 檔案,二者的結構不同,解析自然也不相同,並且 *.aab 中的檔案包含 dynamic feature 目錄,所以 *.aab 中需要混淆更多的檔案內容。

AAB 檔案的解析

AabResGuard 是依賴於 bundletool 來完成 .aab 檔案的解析、修改等相關操作的,而 bundletool 不同的版本之間差異較大,不同的版本之間可能會有一些相容問題。

目前 AabResGuard 依賴了 bundletool-0.10.0 版本,如果通過 gradle 配置引入 AabResGuard,可能會覆蓋 AGP(Android gradle plugin) 本身依賴的 bundletool 版本,從而導致版本的相容問題。

為了解決這個問題我們是通過使用 Shadow (https://imperceptiblethoughts.com/shadow/) 對引入的其他庫的 package 重定向並且解除了 AabResGuard-plugin 中對 bundletool 的傳遞依賴。

資源混淆

最小字元替換,AabResGuard 會對資原始檔進行混淆,替換原始的資源名稱、路徑為最短字元,以達到縮減包體積和資源保護的作用。

一個資源的組成有這麼幾部分:id、name、path 等,我們混淆的內容為:name、path,這二者在原始檔案中預設是一一對應的(name 即為 path 的檔名稱),但其實這二者並無關聯,如果混淆後還是以 name 作為 path 的名稱,無疑會造成空間的浪費。

如果 res/drawable-xxhdpi 路徑下只有一個檔案的話,無疑會造成兩個字元的空間浪費。

AabResGuard 對每個資料夾下的檔案和不同 type 的資源名稱均採用單獨混淆的方式,以保證每個資料夾下的檔案和每種資源均為最短路徑。

並且輸出的 mapping 中儲存了檔案的資源 id,方便遇到問題後進行快速定位資源。

檔案去重

AabResGuard 會對包中的重複資源進行 md5 去重 ,md5 相同的資原始檔只會保留一份,並且會重定向 resources.pb 中被去重的資原始檔路徑。

檔案去重在 tiktok 上減小了 4050 個檔案,減小檔案大小 0.6MB,由於 tiktok 對資源還有其他方面的優化,所以部分資源大小本身較小,不同應用的收益不同,以實際收益為準。

文案過濾

工程中除了無用資原始檔之外,還有一些字串資源(包括語言)也是無效的,這部分資源也會佔用包體積,這部分資源是可以進行移除的,通過更改 resources.pb 檔案來移除這部分資源以達到縮減包體積的作用。

事實證明,資源中佔比最大的還是字串資源,通過對無用字串的移除,這部分收益可觀,在 tiktok 上減少字串個數 3691 個,減少語言 37 種,最大收益可達 2.5M。

AabResGuard 的特性與使用特性資源去重:對重複資原始檔進行合併,縮減包體積。檔案過濾:支援對 bundle 包中的檔案進行過濾,目前只支援 MATE-INFO/、lib/ 路徑下的過濾。白名單:白名單中的資源,名稱不予混淆。增量混淆:輸入 mapping 檔案,支援增量混淆。文案刪除:輸入按行分割的字串檔案,移除文案及翻譯。使用命令列工具:支援命令列一鍵輸入輸出。Gradle plugin:支援 gradle plugin,使用原始打包命令執行混淆。Gradle plugin

在 build.gradle(root project) 中進行配置:

在 build.gradle(application) 中配置:

aabResGuard plugin 侵入了 bundle 打包流程,可以直接執行原始打包命令進行混淆。

通過 gradle 獲取混淆後的 bundle 檔案路徑:

命令列支援

AabResGuard 提供了 jar 包,可以使用命令列直接執行。

配置檔案 config.xml,白名單支援「正則表示式」:

resources-mapping

用於記錄資源混淆規則的日誌檔案,示例如下:

res dir mapping: 儲存資原始檔目錄的混淆規則。格式:dir -> dir(res/ 根目錄不可以被混淆)res id mapping: 儲存資源名稱的混淆規則。格式:resourceId : resourceName -> resourceName(增量混淆時,resourceId 不會被讀入)res entries path mapping: 儲存資原始檔路徑的混淆規則。格式:resourceId : path -> path(增量混淆時,resourceId 不會被讀入)-duplicated.txt

用於記錄被去重的資原始檔,示例如下:

AabResGuard 的可擴充套件性強,「資源混淆」、「資源去重」、「檔案過濾」、「字串過濾」等功能均可獨立執行。並且框架的設計使 AabResGuard 不光是針對資源混淆的工具,更多的是提供了方便我們對 *.aab 檔案進行解析、更新等操作。

如:某些情況下我們需要通過 AAB 匯出一個全量的 APK 包,這種情況下匯出的 APK 會包含所有的資源,但是我們希望只有一種維度的 so,我們可以過濾 32 位 so 來生成一個 64 位的 AAB 檔案以達到目的。

如果因為某些特殊需求需要對 *.aab 檔案進行二次修改的話,可以對 AabResGuard 進行擴充套件以快速達到目的。

參考資料

Android app bundle (https://developer.android.com/guide/app-bundle)

AndResGuard (https://github.com/shwenzhang/AndResGuard)

Aapt2 (https://android.googlesource.com/platform/frameworks/base.git/+/master/tools/aapt2)

Bundletool (https://github.com/google/bundletool)

Shadow (https://imperceptiblethoughts.com/shadow/)

Shrinking APKs, growing installs (https://medium.com/googleplaydev/shrinking-apks-growing-installs-5d3fcba23ce2)

最新評論
  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 華為多款手機跑分再次作弊,被GeekBench5移出跑分資料庫