1. 程式人生 > >Android的APK全面瘦身

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瘦身,如果有好的建議大家也可以分享下。程式設計師的最終目標:讓程式碼變得更加簡潔,讓使用者體驗變得更好!