背景
因為我所在的專案是做投放包,對安卓包的大小很敏感,經常會優化包的大小,所以想引入工具靜態檢測包大小,看能不能找到其中可以優化的地方,防患於未然。Matrix是微信終端自研和正在使用的一套APM(Application Performance Management)系統。 Matrix-ApkChecker作為Matrix系統的一部分,是針對android安裝包的分析檢測工具,根據一系列設定好的規則檢測apk是否存在特定的問題,並輸出較為詳細的檢測結果報告,用於分析排查問題以及版本追蹤。Matrix-ApkChecker以一個jar包的形式提供使用,通過命令列執行 java -jar ApkChecker.jar 即可執行。
Matrix-ApkChecker的使用
在git上下載matrix-apk-canary-0.4.10.jar
直接在命令列執行
java -jar ApkChecker.jar
即可以檢視Matrix-ApkChecker的使用說明 (注意:下面所說的路徑為完整路徑,非相對路徑)
Matrix-ApkChecker的命令列引數比較多,主要包括global引數和option引數兩類:
- global
--apk 輸入apk檔案路徑(預設檔名以apk結尾即可)
--mappingTxt 程式碼混淆mapping檔案路徑 (預設檔名是mapping.txt)
--resMappingTxt 資源混淆mapping檔案路徑(預設檔名是resguard-mapping.txt)
--input 包含了上述輸入檔案的目錄(給定--input之後,則可以省略上述輸入檔案引數,但上述輸入檔案必須使用預設檔名)
--unzip 解壓apk的輸出目錄
--output 輸出結果檔案路徑(不含字尾,會根據format決定輸出檔案的字尾)
--format 結果檔案的輸出格式(例如 html、json等)
--formatJar 實現了自定義結果檔案輸出格式的jar包
--formatConfig 對結果檔案輸出格式的一些配置項(json陣列格式)
global 引數之後緊跟若干個 Option,這些 Option 是可選的,一個 Option 表示針對 apk 的一個檢測選項。
- option引數
- manifest 從AndroidManifest.xml檔案中讀取apk的全域性資訊,如packageName、versionCode等。
- fileSize 列出超過一定大小的檔案,可按檔案字尾過濾,並且按檔案大小排序
--min 檔案大小最小閾值,單位是KB --order 按照檔案大小升序(asc)或者降序(desc)排列 --suffix 按照檔案字尾過濾,使用","作為多個檔案字尾的分隔符
- countMethod 統計方法數
group 輸出結果按照類名(class)或者包名(package)來分組
- checkResProguard 檢查是否經過了資源混淆 (AndResGuard)
- findNonAlphaPng 發現不含alpha通道的png檔案
- checkMultiLibrary 檢查是否包含多個ABI版本的動態庫
- uncompressedFile 發現未經壓縮的檔案型別(即該型別的所有檔案都未經壓縮)
suffix 按照檔案字尾過濾,使用","作為多個檔案字尾的分隔符
- countR 統計apk中包含的R類以及R類中的field count
- duplicatedFile 發現冗餘的檔案,按照檔案大小降序排序
- checkMultiSTL 檢查是否有多個動態庫靜態連結了STL
- unusedResources 發現 apk 中包含的無用資源
rTxt R.txt檔案的路徑(如果在全域性引數中給定了--input,則可以省略) ignoreResources 需要忽略的資源,使用","作為多個資源名稱的分隔符
- unusedAssets 發現apk中包含的無用assets檔案
- ignoreAssets 需要忽略的assets檔案,使用","作為多個檔案的分隔符
- unstrippedSo 發現apk中未經裁剪的動態庫檔案
除了直接在命令列中帶上詳細引數外,也可以將引數配置以 json 的格式寫到一個配置檔案中,然後在命令列中使用
指定配置檔案的路徑。一個典型的配置檔案格式如下:
{
"--apk": "/xxx",
"--formatConfig": [
{
"group": [
{
"name": "Android System",
"package": "android"
},
{
"name": "java system",
"package": "java"
},
{
"name": "xxx",
"package": "com.xxx"
}
],
"name": "-countMethod"
}
],
"--format": "mm.html,mm.json",
"options": [
{
"name": "-manifest"
},
{
"--suffix": "png, jpg, jpeg, gif, arsc",
"--min": "10",
"name": "-fileSize",
"--order": "desc"
},
{
"--group": "package",
"name": "-countMethod"
},
{
"name": "-checkResProguard"
},
{
"--min": "10",
"name": "-findNonAlphaPng"
},
{
"name": "-checkMultiLibrary"
},
{
"--suffix": "png, jpg, jpeg, gif, arsc",
"name": "-uncompressedFile"
},
{
"name": "-countR"
},
{
"name": "-duplicatedFile"
},
{
"name": "-unusedAssets",
"--ignoreAssets": [
"*.so"
]
}
],
"--output": "/xxx"
}
其中,mm.html 和 mm.json 是微信使用的自定義輸出格式,Matrix-ApkChecker 預設提供 html 、json、mm.html 以及 mm.json 四種輸出格式。
要注意的是所有路徑都必須是絕對路徑,如果是windows系統的話複製資料夾的路徑是反斜槓(),會報轉義錯誤,改為正斜槓(/)
使用配置檔案命令如下:
java -jar matrix-apk-canary-0.4.10.jar --config 配置檔案路徑
輸出這麼一串程式碼就代表執行成功
Matrix-ApkChecker的功能
- 讀取manifest的資訊
從AndroidManifest.xml檔案中讀取apk的全域性資訊,如packageName、versionCode等
- 按檔案大小排序列出apk中包含的檔案
列出超過一定大小的檔案,可按檔案字尾過濾,並且按檔案大小排序
- 統計方法數
統計dex包含的方法數,並支援將輸出結果按照類名(class)或者包名(package)來分組
- 檢查是否經過了資源混淆(AndResGuard)
檢查apk是否經過了資源混淆,推薦使用資源混淆來進一步減小apk的大小
- 搜尋不含alpha通道的png檔案
對於不含alpha通道的png檔案,可以轉成jpg格式來減少檔案的大小
- 檢查是否包含多個ABI版本的動態庫
so檔案的大小可能會在apk檔案大小中佔很大的比例,可以考慮在apk中只包含一個ABI版本的動態庫
- 搜尋未經壓縮的檔案型別
某個檔案型別的所有檔案都沒有經過壓縮,可以考慮是否需要壓縮
- 統計apk中包含的R類以及R類中的field count
編譯之後,程式碼中對資源的引用都會優化成int常量,除了R.styleable之外,其他的R類其實都可以刪除
- 搜尋冗餘的檔案
對於兩個內容完全相同的檔案,應該去冗餘
- 檢查是否有多個動態庫靜態連結了STL
如果有多個動態庫都依賴了STL,應該採用動態連結的方式而非多個動態庫都去靜態連結STL
- 搜尋apk中包含的無用資源
apk中未經使用到的資源,應該予以刪除
- 搜尋apk中包含的無用assets檔案
apk中未經使用的assets檔案,應該予以刪除
- 搜尋apk中未經裁剪的動態庫檔案
動態庫經過裁剪之後,檔案大小通常會減小很多
示例分析
下面,我們對一個示例apk使用Matrix-ApkChecker進行檢查,並根據檢查的結果進行鍼對性的減包優化。
從Matrix-ApkChecker的輸出結果中可以看到示例apk的相關全域性資訊如下圖所示:
示例 apk 中包含的檔案按型別統計如下圖所示:
png檔案(不包括 .9.png)未經壓縮,可以考慮一定程度的壓縮
存在一些冗餘的檔案,檔案內容相同的檔案應該只保留一份
存在無用資源,包括未使用的系統support包中的資源、第三方資源包中的無用資源以及示例app定義的資源
存在無用的assets資源,應該刪除
後續
瞭解完Matrix-ApkChecker的基本功能後,後續考慮整合到jenkins中,每次編譯產出Apk時執行指令碼記錄apk的總大小值,對比每個版本的包大小總值,dex、so、圖片資源各自佔比、是否有重複資源、是否有圖片未壓縮等,如果能每個版本檢查出上述問題並提出優化建議,那麼在持續整合中價值就比較大
參考
https://github.com/Tencent/matrix/wiki/Matrix-Android-ApkChecker