APK瘦身便是對APK大小進行壓縮策略,減少APK安裝包大小,更小的安裝包更有助於吸引用戶安裝。前一段時間我司某一App進行APK的瘦身,最終也達到了減少10M的目標,現作一個簡單的總結記錄。android
須要對一個App進行瘦身,首先最重要的就是對App大小有一個大體的瞭解,最直觀看到App的大小就是經過Android Studio自帶的Analyzer進行APK的分析。使用方法:git
一、將一個apk拖動到Android Studio的編輯器窗口
二、在Project窗口中,雙擊build/output/apks/目錄下的apk
三、在菜單欄中選擇選擇Build > Analyze APK,而後選擇要分析的apk
複製代碼
獲取如上圖1所示的APK Size分析圖以後,咱們就能夠針對這裏面的目錄進行鍼對性的優化。github
如圖最上方所示的APK Size就是咱們應用打包以後的大小,Download Size則是上傳到Google Play以後,用戶下載的大小。因此咱們通常能夠只針對前一項的APK Size進行對比。web
從上圖Analyzer能夠發現,一個APK主要包含以下目錄:安全
除此以外,還包含了以下的文件:bash
resources.arsc:包括了全部能夠被編譯的位於res/values/目錄下的XML資源。打包工具在打包過程當中會把XML的內容編譯成二進制的形式,亦或者把相關資源的引用路徑編譯成二進制,而後整合到該文件裏面。例如string文件、layout的路徑、圖片的路徑等。微信
classes.dex:包含了全部的Java文件編譯後的class文件,class文件最終轉化成該dex文件。通常文件都比較大,有的App有幾個dex文件,這是由於單個DEX文件限制方法數在65536,因此當代碼量過大時,就須要經過multiDex進行分包,拆分紅多個dex文件,解決這個問題。架構
AndroidManifest.xml:整合了多個module的AndroidMainifest文件的權限、聲明等配置到該文件。app
知道了APK的組成部分,那麼咱們就能夠針對這些文件/文件夾進行鍼對性的優化,每一個App都不同,可是方法都是大同小異,本文講述瘦身策略也是針對這些目錄和文件進行優化,這樣能夠顯得更加有條理性。編輯器
Android系統如今支持7種CPU架構,每一種都關聯着對應的ABI(二進制接口,Application Binary Interface),而每一種ABI都定義了二進制文件(尤爲是.so文件)如何運行在相應的系統平臺上,從使用的指令集,內存對齊到可用的系統函數庫等。因此若是咱們的App須要適配不一樣的CPU架構的話,以下圖2所示,就須要放入不一樣架構的文件夾下都放入不一樣的so文件,在打包時,這些so都會放在lib目錄下。由此,若是咱們想減少lib目錄的大小,無非就以下一些常見的策略。
對App引入的so文件進行確認哪些是不須要的,哪些是能夠進行裁剪壓縮的,哪些是能夠避免引入的。例如若是引入的so須要下載上傳功能而多引入了一個cURL庫致使so增大,這時就可讓Java層代碼定義接口,讓so來調用,從而避免引入cURL庫;再如Fresco庫,若是不須要webP圖,或者不須要webP動圖功能,而後減小Fresco庫的依賴,一樣能夠減少so的大小。
Android系統如今支持不少種CPU架構(如mips、arm、x86等),市面上主流機型都是arm架構,x86和mips類型極少。因此能夠有選擇地保留某些架構的so,從而下降lib文件夾的大小。可是我建議你在開始前先對用戶手機的cpu型號進行一次統計,分析自身App對應架構手機的佔有率,這樣你才能大膽的進行操做,通常只保留armeabi或者armeabi-v7a便可。操做也是比較簡單,只須要在根目錄的build.gradle下配置:
android {
buildTypes {
ndk {
abiFilters "armeabi-v7a"
}
}
}
複製代碼
若是你的App須要支持多種架構,那麼就能夠在abiFilters
裏面把多種架構加進去,固然你也能夠只保留一種,而後分渠道打包,如Google Play就支持arm和x86等多個渠道打包。
res目錄通常也是佔APK Size大頭的一個目錄,以下圖,這個目錄通常都是圖片資源佔空間比較多,尤爲當App爲了適配多種分辨率而存放了多套圖時,這時候就會致使res目錄打下會很是大。而這個目錄的優化方式也是比較多,下面就簡單列舉一下:
由於Android設備在加載圖片時會優先加載對應分辨率文件夾下的圖片,若是對應分辨率文件下沒有所要的圖片,則找高分辨率對應文件夾下的圖片。那是否是咱們把圖片放在最高分辨率的文件夾下就能夠了呢?不是的!由於若是這樣會致使低分辨率手機加載圖片時會消耗更多的內存,並且是指數級別增加的,因此若是盲目地放在一個目錄是不合適的。目前不一樣分辨率對應優先加載的文件夾中圖片以下,若是是針對國內用戶的App能夠只保留xxhdpi目錄,而若是是東南亞市場的App則能夠只保留xhdpi。
320*240 ldpi
480*320 mdpi
800*480 hdpi
1280*720 xhdpi
1920*1080 xxhdpi
複製代碼
針對一些非重要的圖片,能夠選擇動態在線加載,嚴格來講,非首頁的圖片均可以動態加載,固然,爲了提高用戶體驗,咱們會把圖片放在本地。可是,一些使用場景很是小或者大小較大的圖片,大膽刪掉,選擇動態加載吧!
可使用一些圖片壓縮網站或者工具壓縮你的資源文件吧,例如TinyPng、ImageOptim、Zopfli、智圖等。
若是你的App只支持Android4.0以上的話,能夠把png格式的圖片轉爲webp,相同畫質下體積更小。
在多人開發過程當中,一般都會有漏刪無用資源的問題,圖片資源也不例外,例如須要刪除一個模塊的代碼時,很容易就會漏刪資源文件,因此能夠按期使用lint檢測出無用的資源文件,原理這裏不做介紹,使用方法很是簡單,能夠直接在AS裏面使用,以下圖所示。注意:lint檢查出來的資源都是無直接引用的,因此若是咱們經過getIdentifier()方法引用文件時,lint也會標記爲無引用,因此刪除時注意不要刪除經過getIdentifier()引用的資源。
Analyze -> Run Inspection by Name -> 輸入:Unused resources -> 跳出彈框選擇範圍便可
複製代碼
shrinkResources是在編譯過程當中用來檢測並刪除無用資源文件,也就是沒有引用的資源,minifyEnabled 這個是用來開啓刪除無用代碼,好比沒有引用到的代碼,因此若是須要知道資源是否被引用就要配合minifyEnabled使用,只有二者都爲true時纔會起到真正的刪除無效代碼和無引用資源的目的。打開方式也是很是簡單,在build.gralde文件裏面打開便可:
android {
buildTypes{
minifyEnabled true
shrinkResources true
}
}
複製代碼
assests目錄存放的一般是一些經過AssetManager可以檢索到的資源,包括MP三、視頻、字體、webp的資源,各個App存放內容都很大不相同,列舉一些經常使用的優化方案。
中文字體通常都比較大,由於字體文件包含了中文好幾千個漢字,可是咱們實際上在App中並不會所有都使用,甚至咱們只用到其中的幾個字,這時候咱們就能夠把字體文件進行刪減,在Github上面有一個字體提取工具FontZip,使用方法也是很是簡單,有興趣能夠去star一下。
一些MP三、視頻、Webp等資源能夠在使用到時再進行下載,不須要放在本地。
一些MP三、視頻、Webp等資源若是必須放在本地,能夠壓縮成zip文件或者使用7zip進行壓縮,在使用到時再進行解壓,減少空間的佔用。
該目錄下的MANIFEST.MF、CERT.SF、INDEX.LIST、CERT.RSA等文件主要是存放一些APK文件加密後的信息,用以校驗APK的完整性和安全性,這個目錄沒有太好的優化方式,並且文件通常也比較小,不會超過1M。
這個文件包含全部能夠被編譯的位於res/values/目錄下的XML資源,以下圖5所示是淘寶APK的resources.arsc文件,像圖片的引用名字、layout文件的引用名字、string資源等都被編譯到了這個文件裏面。
因此若是咱們須要對resources.arsc文件進行優化,無非就是對路徑名字進行混淆,刪除無用的資源映射,前者可使用AndResGuard,後者可使用lint等進行檢測。
大部分應用都不須要支持幾十種上百種語言,因此在咱們引用一些第三方庫時(如Google、Facebook的庫),它們每每帶有上百種多語言資源,而大部分多語言對於咱們本身的應用是沒有用處的,咱們只須要在build.gralde
裏面進行以下配置便可完成無用語言資源的刪除,這樣在打包的時候就會排除私有項目、android系統庫和第三方庫中非中文的資源文件了,效果仍是比較顯著的。
android {
//...
defaultConfig {
// 只保留中文
resConfigs "zh"
}
}
複製代碼
AndResGuard是一個幫助你縮小APK大小的工具,他的原理相似Java Proguard,可是隻針對資源。他會將本來冗長的資源路徑變短,例如將res/drawable/wechat變爲r/d/a。詳細使用方法參照Github,很簡單有效地減少resources.arsc文件大小。以下圖6和圖7所示,圖6是壓縮前的效果,圖7是壓縮完的效果,若是是資源比較多的App,壓縮效果也是立竿見影。
使用方法也是很是簡單,在build.gradle
文件中進行以下配置便可:
andResGuard {
mappingFile = null
use7zip = true
useSign = true
keepRoot = false
whiteList = [
//for your icon
"R.drawable.icon",
//for fabric
"R.string.com.crashlytics.*",
//for umeng update
"R.string.umeng*",
"R.string.UM*",
"R.layout.umeng*",
"R.drawable.umeng*",
//umeng share for sina
"R.drawable.sina*"
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"resources.arsc"
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.1.9'
//path = "/usr/local/bin/7za"
}
}
複製代碼
Dalvik是Android平臺運行時的環境,可是Dalvik虛擬不支持直接執行Java的字節碼,因此會對編譯生成的 .class 文件進行翻譯、重構、解釋、壓縮等處理,這個處理過程是由 dx 進行處理,處理完成後生成的產物會以 .dex 結尾,稱爲Dex文件。
像淘寶、微信這些App,若是咱們分析它們的APK能夠發現,它們有多個Dex文件,以下圖8所示,這是由於單個Dalvik Excutable(DEX)字節碼文件內的方法數不能夠超過65536個,因此須要DEX分包配置來避免這個限制,使應用可以構建並讀取DEX文件。
Proguard是一款免費的Java類文件壓縮器、優化器和混淆器,Android Studio已經集成了這個工具,只要通過簡單的配置,便可完成,以下代碼所示,在build.gradle裏面設置minifyEnabled
爲ture,同時在proguardFiles
指向proguard的規則文件便可。
android {
buildTypes{
minifyEnabled true
proguardFiles 'proguard.cfg'
}
}
複製代碼
App瘦身是一個長期的過程,建議能夠進行每一個版本對APK大小進行監控,列出增長和減少的點,作到持續的統計和追蹤,從而給公司帶來效益。