頭條APK瘦身之路

隨著版本迭代,功能增加安裝包體積也會慢慢增大。

今日頭條576版本APK達到了25M,通過一系列的優化,到目前的607版本為12M。本文主要是介紹頭條APK瘦身中用到的一些方法。

APK分析

既然是要優化APK的大小,那首先就得看下APK文件的構成。

Android Studio在2.2版本添加 APK Analyzer功能,可以直接打開apk文件,如下圖所示

APK文件主要有如下幾部分組成:

res主要是存放圖片資源

       lib主要是存放so庫,各個cpu架構

       classes.dex是java源碼編譯后生成的java字節碼文件,因方法數限制拆分了多個dex

       assets主要存放不需要編譯處理的文件

       resources.arsc是編譯后的二進制資源文件,包括圖片、文本索引等

       META-INF 簽名信息

       AndroidManifest.xml 描述配置文件

從APK的構成中可以看出占比較大的幾個部分,可以著重對其優化

優化

res文件夾

圖片資源壓縮

1、 ImageOptim

提供了相應客戶端,支持通過客戶端批量處理,mac上可以使用如下命令開啟:

find . -name '*.png' | xargs open -a ImageOptim

2、 TinyPng

沒有提供客戶端,支持拖拽到網頁處理;提供了HTTP API來批量處理,但是有數量限制,每個key每個月可以壓縮500張。 開發了一個gradle插件來批量操作,網上也有一些類似的插件: TinyPng Gradle插件

移除無用資源

1、通過使用Lint檢測刪除無用資源,某些業務代碼刪除的時候遺漏了相應資源,可以寫個腳本檢測移除不再使用的資源

2、添加shrinkResources設置項( 官方說明 ),有0.18M的優化空間,但是該設置有風險如果要使用需要做好測試

3、選擇支持合適的圖片,目前有ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi資源文件夾,可根據自己app的用戶設備選擇支持2-3種即可(當然一套也行)

高版本的gradle已不再支持通過resConfigs "nodpi", "hdpi", "xhdpi", "xxhdpi"配置支持的資源,只能人肉刪除。如果你只想打包某一種屏幕密度的資源,可以使用分包策略,添加如下density配置可以只支持打包xhdpi資源(如果出現某些資源xhdpi沒有,而其他文件夾包含的情況也不用擔心,gradle會保留相應資源),這種配置最終會出多個apk包,具體介紹可參看 官方說明

splits {
    density {
        enable true
        reset()
        include "xhdpi"
        compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
}

4、如果想整體移除res下某個文件夾可以添加如下aaptOptions配置,而不用打包時手工刪除,多個文件夾用:隔開

aaptOptions {
    ignoreAssetsPattern 'color-night-v8:drawable-night-v8'
}

arsc文件

resource.arsc文件記錄了資源id和資源的對應關系(字符串的內容,圖片的相對路徑等)

減少語言支持

目前包括各種語言(v7包引入),點擊resources.arsc可以看到支持80種 可以通過修改gradle配置,去除不需要部分,這里我們保留4種

defaultConfig {
    resConfigs "zh-rCN", "zh-rHK", "zh-rTW", "en"
}

只保留"zh-rCN", "zh-rHK", "zh-rTW", "en" 減少不必要的語言(80種減到5種,有一個default)apk可減少0.61M

資源混淆

開源解決方案 AndResGuard 可以看下,通過使用段路徑和壓縮可以減小apk,需要注意的是你的項目中某些資源需要keep,減少了1.5M。

lib文件夾

架構支持

Android系統目前支持以下七種不同的CPU架構:ARMv5,ARMv7 (從2010年起),x86 (從2011年起),MIPS (從2012年起),ARMv8,MIPS64和x86_64 (從2014年起)

每一個CPU架構對應一個ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64

所有的x86、x86 64、armeabi-v7a、arm64-v8a設備都支持armeabi架構的.so文件,x86設備能夠很好的運行ARM類型函數庫,但并不保證100%不發生crash,特別是對舊設備。64位設備(arm64-v8a, x86 64, mips64)能夠運行32位的函數庫,但是以32位模式運行,在64位平臺上運行32位版本的ART和Android組件,將丟失專為64位優化過的性能(ART,webview,media等等)。所以一般的應用完全可以根據自己業務需求選擇使用armeabi或者armeabi-v7a一種支持就行。

可以通過gradle配置

defaultConfig {
    ndk {
        abiFilter "armeabi"
    }
}

比如:微信、微博、QQ只保留了armeabi,非死book、推ter、Instagram只保留了armeabi-v7a

假設只支持了armeabi,如果有特殊要求(比如視頻應用)需要用到部分armeabi-v7a的so,可以通過改名放到armeabi文件夾中,根據手機實際情況選擇加載。

動態下發

比較大的so可以選擇動態下發的形式延遲加載,代碼上需要加一些判斷邏輯。

dex文件

1、添加設置minifyEnabled true,混淆、壓縮代碼,這個設置現在app應該都已經添加了。

2、刪除一些無用庫,早期為了兼容低版本手機,添加了一些兼容庫,隨著時間推移APP支持的最低版本也在升高,之前的一些無用庫就可以移除。

3、插件下發業務模塊 添加插架框架,將部分代碼延遲下發加載,這部分效果顯著。

其他

極端情況下可以考慮以下兩種方式,可以優化約1M的空間

debug信息

一般我們會配置Proguard保留行號等信息用于線上日志分析,極端情況下也可考慮移除這部分,會有5%-10%的效果,可以減少了0.5M,但是出于方便性暫未移除。

-keepattributes SourceFile,LineNumberTable

supportv7包

如果對supportv7包依賴的不多,可以直接把使用到的內容copy出來單獨處理,畢竟該包會增加至少0.4M的體積,業務復雜后這部分并不好操作和后續維護,頭條暫時并沒有使用。

TODO

功能迭代不止,瘦身事業不息。

要維持和繼續減小apk包,必須要不斷優化,現在又如下思路還沒有實施,可以看下

1、Google的support-v4包新版本已經做了拆分,24.2.0版本拆分成了5個module:support-compat、support-core-utils、support-core-ui、support-media-compat、support-fragment,可以根據自己需要單獨引用相應的module。

v7包也會依賴v4,maven依賴有個好處,可以通過exclude單獨剔除相應依賴,如下:

compile ('com.android.support:appcompat-v7:24.2.0') {
       exclude module: 'support-v4'
       }
       compile 'com.android.support:support-fragment:24.2.0'

不過目前各家APP對于support包的使用較深,support包各模塊也會有相關依賴關系,具體能不能使用還需要看實際情況了。

2、使用 ReDex 優化,這是非死book開源的一個減小安卓app大小以提高性能的工具,集成的話有風險需要多測試, 教程

3、減少java隱藏開銷,比如一些自動生成的函數等。

 

來自:https://techblog.toutiao.com/2017/05/16/apk/

 

 本文由用戶 qvdi6133 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!