Android的APK全面瘦身
隨著APK功能越來越多、越來越複雜,APK的體積也變得越來越大。當用戶去看APK描述時,驚歎:哇!這麼多功能,趕緊下載來玩一下。但使用者真正點選下載後,發現APK體積這麼大,擦!如果沒WIFI,下載又耗流量,安裝又佔記憶體。經過衡量後,使用者可能選擇終止下載,這樣一來很容易造成使用者流失。為了更好使用者體驗,我們得保證功能多樣化的同時,APK體積又足夠小。那麼,讓我們共同探討下如何對APK進行全面瘦身。
理解APK結構
APK檔案由ZIP文件組成,包含你應用程式的所有檔案。這些檔案包括:java類檔案、資原始檔和編譯資源。
APK包含以下目錄:
META-INF/:包含CERT.SF和CERT.RSA簽名檔案,也包含MANIFEST.MF檔案;
assets/:包含app的assets,可以通過AssetManager物件來檢索;
res/:包含沒有編譯進resource.arsc檔案的資源;
lib/:包含編譯程式碼,各種平臺架構:armeabi,armeabi-v7a,armeabi-v8a,x86,x86_64,mips;
resource.arsc:包含編譯資源,打包工具抽取XML內容,編譯成二進位制格式,並且儲存起來;
class.dex:編譯成DEX格式檔案,讓ART/Dalvik虛擬機器能夠識別;
AndroidManifest.xml:包含Android核心的manifest檔案,四大元件、包名、版本號、版本名稱、許可權等等;
移除無用資原始碼
Android Studio自帶的lint工具,用於靜態程式碼分析,檢查你/res目錄下的沒有引用的檔案。當lint工具在你的工程發現潛在的無用程式碼時,會列印如下資訊:
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
to be unused [UnusedResources]
另外,在gradle.build配置檔案新增程式碼混淆:
只需支援特定畫素密度android { buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
Android支援各種型號裝置,每種型號的螢幕密度不同。在Android4.4及以上,支援解析度包括:ldpi、mdpi、hdpi、xhdpi、xxhdpi和xxxhdpi。我們沒必要適配所有裝置,只需要選擇特定解析度進行適配,這樣可以減少圖片資源的引入。
減少動畫幀數
幀動畫對APK體積影響很大。例如,原來引入30幀動畫,可以在不影響動畫效果前提下,適當減少幀數。
使用Drawable物件
一些圖片並不需要靜態圖片資源,這種情況下,我們可以使用Drawable代替靜態圖片。這樣可以減少圖片資源。
複用資源
可以為影象的變化新增單獨資源,比如:淺色、形狀、旋轉等。但是,推薦複用相同資源,在執行時再自定義改變。Android提供幾種方式來改變顏色,Android5.0以上,可以使用android:tint和android:tintMode。如果是Android5.0以下,可以採用ColorFilter類進行設定。你也可以刪除原有旋轉效果資源,使用相同效果更加簡單方式實現。以下程式碼用於實現箭頭的展開與收起,通過把原圖旋轉180°:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_arrow_expand"
android:fromDegrees="180"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="180" />
優化PNG檔案
aapt工具可以在編譯過程使用無失真壓縮方式,優化res/drawable目錄的圖片資源。比如,aapt工具可以使用顏色調色盤,不需要256種color情況下,把true-color的PNG圖片轉成8位。這樣圖片質量不變,但是所佔記憶體更小。你需要在gradle進行如下配置:
aaptOptions {
cruncherEnabled = false
}
壓縮PNG和JPEG檔案
你可以使用有失真壓縮工具:pngcrush、pngquant或者zopflipng,對PNG檔案進行壓縮。可以使用packJPG工具對JPEG檔案進行壓縮。
webP格式用起來
在你的圖片中,你可以使用webP格式代替PNG或者JPEG。webP提供有失真壓縮(像JPEG一樣),也提供透明度處理(像PNG一樣)。但是,可以壓縮效果比PNG和JPEG好。你可以在android Studio裡把PNG或者JPEG格式圖片轉換成webP格式,選中圖片右擊,最後一欄:
看下webP與jpg對比,圖片質量相同,但webP格式所佔記憶體要小一點:
使用向量圖
你可以使用向量圖建立獨立解析度的圖示,使用這些圖片可以顯著減少你APK體積。在Android中,向量圖是以VectorDrawable物件來表示。使用向量圖,100個位元組的檔案可以生成螢幕大小的清晰影象。具體用法如下:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="64dp"
android:width="64dp"
android:viewportHeight="600"
android:viewportWidth="600" >
<group
android:name="rotationGroup"
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="45.0" >
<path
android:name="v"
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
</group>
</vector>
但是,向量圖需要很長時間來渲染。這算是以時間換空間的代價。考慮到這點,只在圖片比較小的情況下,才採用向量圖。
移除列舉
一個列舉變數可以在class.dex檔案裡增加1.0到1.4KB。這些額外體積會迅速增加系統和共享庫的複雜性。可以的話,使用@IntDef和ProGuard把列舉變數移除掉,並且把他們轉換成整型。
大半夜寫部落格的好處是安靜,雖然有點困。希望這篇文章可以幫助大家成功實現APK瘦身,如果有好的建議大家也可以分享下。程式設計師的最終目標:讓程式碼變得更加簡潔,讓使用者體驗變得更好!