APK包的主要結構如下圖,對於大部分項目中文件實際佔用空間大小排序正如圖中從上到下。
代碼
- 開啓Proguard,一方面可以降低代碼被反編譯後的可讀性,另一方面也可以減小包體積。
- 刪除debug信息,參考支付寶方案:支付寶 App 構建優化解析:Android 包大小極致壓縮
Dex:
- dex分包優化,跨dex調用會導致method id等信息需要同時存在於調用與被調用的dex文件中,這就造成了信息冗餘,所以就需要儘量減少跨dex的調用
- dex壓縮,參考Facebook方案,Facebook App 的 classes.dex 只是一個殼,真正的代碼都放到 assets 下面,他們把所有dex文件合併成了一個文件secondary.dex.jar.xzs,並通過xz壓縮
so文件:
-
只保留一個abi平臺,如armeabi-v7a
-
儘量使用精簡版so,只保留自己項目中使用到的功能
-
檢查是否存在多個動態庫都依賴了STL,如果存在則應該採用動態鏈接的方式而非多個動態庫都去靜態鏈接STL
-
搜索apk中未經裁剪的動態庫文件,動態庫經過裁剪之後,文件大小通常會減小很多
資源文件:
-
開啓資源混淆:
1、因爲資源索引文件 resources.arsc 需要記錄資源文件的名稱與路徑,使用混淆後的短路徑 res/s/a,可以減小文件大小
2、metadata 簽名文件。簽名文件 MF 與 SF都需要記所有文件的路徑以及它們的哈希值,使用短路徑可以減小這兩個文件
3、apk打包基於zip壓縮,zip壓縮格式需要記錄每個文件 Entry 的路徑、壓縮算法、CRC、文件大小等信息。使用短路徑,本身就可以減少記錄文件路徑的字符串大小。 -
雖然AndroidStudio支持 lint 和 shrinkResources 功能,在打包過程中會將未引用資源替換成同名的空文件,但文件名稱與路徑還是被記錄在resources.arsc中了,所以依然建議主動刪除項目中未引用的資源,從而減小resource.arsc文件大小。
Lint 作爲一個靜態掃描工具,它最大的問題在於沒有考慮到 ProGuard 的代碼裁剪。在 ProGuard 過程我們會 shrink 掉大量的無用代碼,但是 Lint 工具並不能檢查出這些無用代碼所引用的無用資源。
-
搜索不含alpha通道的png文件,可以將其轉換成jpg格式減小文件大小。
-
搜索冗餘的文件,對於兩個或多個內容完全相同的文件,應該只保留一個。
-
資源合併,將所有資源文件合併成一個大文件。