一.概述
眾所周知君仆,App包體積大小的重要性不言而喻,對(duì)于客戶來說,小體積的包意味著更少的消耗流量返咱,更快的下載時(shí)間钥庇,也意味著更多客戶愿意下載嘗試,意味著客戶量的增加咖摹。
隨著日常業(yè)務(wù)的迭代评姨,餓了么的物流App在最新的版本中漸漸達(dá)到22M,雖然在日常開發(fā)中我們就有著嚴(yán)格要求盡可能的不引入大型三方庫萤晴,使用盡可能小的圖片等來控制App的大小吐句,但是隨著突破20M大關(guān),團(tuán)隊(duì)決定來一次整體優(yōu)化店读。
二.預(yù)覽
首先對(duì)App進(jìn)行分析中嗦枢,我們可以看到APK的構(gòu)成。
APK包含以下目錄:
META-INF/:包含CERT.SF和CERT.RSA簽名文件两入,以及MANIFEST.MF清單文件净宵。
assets/:assets包下存放的資源敲才,這個(gè)文件夾下面的資源文件是不會(huì)被編譯優(yōu)化的裹纳。
-
resources.arsc:App已編譯的資源的資源索引表。此文件包含來自res / values /文件夾的所有配置的XML內(nèi)容紧武。
-
res/:存放 drawable,layout,anim,color,menu,raw等資源剃氧。
lib/:包含特定處理器的軟件層的編譯代碼。此目錄包含每個(gè)平臺(tái)類型的子目錄阻星,如armeabi朋鞍,armeabi-v7a,arm64-v8a妥箕,x86滥酥,x86_64和mips。
classes.dex:dex字節(jié)碼文件畦幢。
AndroidManifest.xml:包含核心Android清單文件坎吻。
Apk中的res下面的資源已經(jīng)占到了6.7M,classes.dex文件加起來有7.6M。因此宇葱,我們打算先從這兩個(gè)地方開始下手瘦真。
三.優(yōu)化方案
A.classes.dex代碼壓縮
1.混淆代碼
在gradle使用minifyEnabled進(jìn)行Proguard混淆的配置,可大大減小APP大惺蚯啤:
android {
buildTypes {
release {
minifyEnabled true
}
}
}
2.Proguard
Proguard是編譯時(shí)對(duì)java代碼進(jìn)行壓縮诸尽,混淆,優(yōu)化印颤,預(yù)編譯等操作的集成化工具您机。Proguard
會(huì)去掉無用的代碼。Proguard也會(huì)混淆重命名代碼。
具體的proguard介紹有很多文章往产,我們就不再這里贅述被碗。
因?yàn)橹暗拇a緣故,我們?cè)趐roguard-rules.pro中開啟了這兩個(gè)命令關(guān)掉了proguard的壓縮無用代碼和優(yōu)化dex字節(jié)碼的功能
-dontshrink
-dontoptimize
因此我們現(xiàn)在去掉這兩個(gè)命令仿村,重新打包查看.
我們看到縮小300KB,具體的變化在于class.dex大小
3.開啟shrinkResources去除無用資源
在app/build.gradle打開shrinkResources:
android {
buildTypes {
release {
...
minifyEnabled true
shrinkResources true
...
}
}
}
shrinkResources必須和minifyEnabled一起用锐朴,shrinkResources要生效也必須打開minifyEnabled。
開啟后效果非常明顯蔼囊,縮小了600K焚志。
4.as自帶的lint檢查工具
刪除無用代碼:使用Android Studio的Lint,步驟:點(diǎn)擊菜單欄 Analyze -> Run Inspection by Name -> unused declaration
刪除無用資源:使用Android Studio的Lint畏鼓,步驟:點(diǎn)擊菜單欄 Analyze -> Run Inspection by Name -> unused Resource
然后就會(huì)檢查出很多無用的東西酱酬,自行去進(jìn)行代碼的刪除檢查等等工作
B.配置resConfigs刪去多余的語言包
因?yàn)轫?xiàng)目目前只要支持中文,所以我們決定只保留中文包
android {
defaultConfig {
...
//只支持中文
resConfigs "zh"
}
}
可以看到效果是非常明顯的云矫,小了快700KB
C.res下資源處理
接下來我們看到在res文件下膳沽,drawable文件是占據(jù)了大頭,因此我們要對(duì)圖片進(jìn)行一些處理让禀。
1.使用一套圖片
因?yàn)閍ndroid雖然要進(jìn)行各種屏幕分辨率的適配挑社,但是其實(shí)我們只需要xhdpi或xxhdpi版本的一套圖片即可,因?yàn)閳D片也會(huì)在不同的分辨率手機(jī)上進(jìn)行縮放自適應(yīng)巡揍。
2.png圖片格式轉(zhuǎn)成jpg
由于UED切的圖都是png格式痛阻,而在項(xiàng)目中一些沒有透明度的圖片,我們都會(huì)將其變?yōu)閖pg格式腮敌,按照往常經(jīng)驗(yàn)來說阱当,一張png圖片轉(zhuǎn)化為jpg后可以減少一半以上的大小。
3.使用其他壓縮工具對(duì)圖片進(jìn)行多次壓縮
在平時(shí)開發(fā)過程中糜工,尤其要隨時(shí)注意圖片的大小問題弊添,在Apk檢查的時(shí)候,要查看圖片大小是否異常捌木,如果一張圖上了20或者30kb油坝,那么就要注意一下是否可以進(jìn)行壓縮。
android在打包過程中aapt會(huì)對(duì)圖片資源大小進(jìn)行優(yōu)化钮莲,但是個(gè)人覺得效果還沒有到想要的效果免钻,因此我們選擇了tinypng工具進(jìn)行圖片的壓縮。
https://tinypng.com/
在壓縮時(shí)可以多次壓縮崔拥,盡量在保證圖片不失色彩的情況下壓縮到盡可能的小极舔。
例如下圖,我們?cè)陧?xiàng)目中發(fā)現(xiàn)這張圖沒有透明度链瓦,并且達(dá)到了98k,于是先將其通過在線轉(zhuǎn)化工具轉(zhuǎn)為jpg格式拆魏,然后通過tintpng多次壓縮盯桦,最終選取了一張效果不錯(cuò),大小適合的渤刃。
可以看到拥峦,前后縮小了整整61KB,在項(xiàng)目中還存在著很多這樣的圖片可以進(jìn)行優(yōu)化,同時(shí)我們也建議在平時(shí)開發(fā)過程中開發(fā)的小伙伴們就要隨時(shí)注意自己使用的圖片大小問題卖子。
其中有一點(diǎn)需要注意的是略号,我們發(fā)現(xiàn).9圖雖然使用了tinypng進(jìn)行壓縮,但是tinpng是將顏色位數(shù)壓縮洋闽,例如把一張24-bit的圖壓為8-bit后玄柠,大小縮小近3倍,但是經(jīng)過aapt優(yōu)化后诫舅,會(huì)把.9圖變回24-bit位數(shù)羽利。
3.webp圖片格式
WebP是谷歌提供的一種支持有損壓縮和無損壓縮的圖片文件格式,而且可以提供比JPEG或PNG更好的壓縮刊懈。
在Android 4.0(API level 14)中支持有損的WebP圖像这弧,在Android 4.3(API level 18)和更高版本中支持無損和透明的WebP圖像。
可以看到webp可以說是極大的減小了圖片的大小尺寸
4.去掉重復(fù)資源
項(xiàng)目中因?yàn)槭褂媚K化的原因虚汛,所以在某些時(shí)間緊迫的迭代中匾浪,在不同的模塊中引入了重復(fù)的圖片,color值等等泽疆,可以通過一些工具查重等找出重復(fù)資源户矢,放在基礎(chǔ)模塊中供給所有上層模塊使用
最后經(jīng)過上面的處理后玲献,Apk減少到了19.5M殉疼。
5.語音文件
在項(xiàng)目中用到了語音文件,我們推薦使用ogg的格式捌年,Ogg文件格式的音質(zhì)和大小相對(duì)于其他語音格式來說已經(jīng)算很好的瓢娜。
6.使用代碼實(shí)現(xiàn)圖片背景效果
一些圓角背景的效果,其實(shí)可以用shape的xml文件進(jìn)行實(shí)現(xiàn)礼预,盡量減少簡(jiǎn)單效果圖片的使用眠砾。
三.lib
對(duì)于lib下的各種so文件包,我們?cè)陧?xiàng)目中只保留了armeabi包下的so文件托酸。
針對(duì)Android 系統(tǒng)的這些拷貝策略的問題褒颈,我們給出了一些配置so的建議:
5.1 針對(duì)armeabi和armeabi-v7a兩種abi
由于armeabi-v7a指令集兼容armeabi指令集,如果可以接受損失一些性能励堡,可以移除armeabi-v7a目錄和其下的庫文件谷丸,只保留armeabi目錄。
目前市面上的x86機(jī)型应结,為了兼容arm指令刨疼,基本都內(nèi)置libhoudini模塊泉唁,即二進(jìn)制轉(zhuǎn)碼支持,該模塊負(fù)責(zé)把ARM指令轉(zhuǎn)換為x86指令揩慕,可以選擇刪掉x86庫目錄亭畜,x86下配置的armeabi目錄的so庫一樣可以正常加載使用。
如果App打算支持64位迎卤,那么64位的so要放全拴鸵,否則可以選擇不單獨(dú)編譯64位的so,全部使用32位的so蜗搔,64位機(jī)型默認(rèn)支持32位so的加載宝踪。比如Apk使用第三方的so只有32位ABI的so,可以考慮去掉Apk中l(wèi)ib目錄下的64位ABI子目錄碍扔,保證Apk安裝后正常使用瘩燥。
四.微信Android資源混淆工具
https://github.com/shwenzhang/AndResGuard
AndResGuard是一個(gè)幫助你縮小APK大小的工具,他的原理類似Java Proguard不同,但是只針對(duì)資源厉膀。他會(huì)將原本冗長(zhǎng)的資源路徑變短,例如將res/drawable/wechat變?yōu)閞/d/a二拐。
AndResGuard不涉及編譯過程服鹅,只需輸入一個(gè)apk(無論簽名與否,debug版百新,release版均可企软,在處理過程中會(huì)直接將原簽名刪除),可得到一個(gè)實(shí)現(xiàn)資源混淆后的apk(若在配置文件中輸入簽名信息饭望,可自動(dòng)重簽名并對(duì)齊仗哨,得到可直接發(fā)布的apk)以及對(duì)應(yīng)資源ID的mapping文件。
這是一個(gè)微信團(tuán)隊(duì)和騰訊很多團(tuán)隊(duì)都在使用的工具铅辞,具體介紹都在上面的鏈接中厌漂。效果還是非常明顯,在我們的項(xiàng)目中縮小了0.8M的大小斟珊。
五.業(yè)務(wù)改造
對(duì)于一些需要用到大量圖片資源的場(chǎng)景苇倡。例如一些新手教程,圖例等囤踩,如果不會(huì)經(jīng)常性的變動(dòng)旨椒,可以嘗試在某些場(chǎng)景使用代碼實(shí)現(xiàn)效果來替代圖片效果,還比如一些控件背景圓角等效果也可以用shape.xml來進(jìn)行替換堵漱。因?yàn)闃I(yè)務(wù)需求综慎,我們的新手教程全部為圖片,我們進(jìn)行改造后減少了700kB大小怔锌。