1. 程式人生 > >Android-APK體積優化與dex方法數超出解決

Android-APK體積優化與dex方法數超出解決

一、Android APK體積優化

1 開啟混淆 則可以去除一些不需要的檔案
minifyEnabled 開啟混淆
shrinkResources 刪除無效的Resource
shrinkResources依賴於minifyEnabled,必須和minifyEnabled一起用

2 圖片壓縮
(1)對於沒有透明區域的png圖片,可以轉成jpg格式
(2)對於體積特別大(超過50k)的圖片資源可以考慮有失真壓縮:jpg採用優圖壓縮,png嘗試採用pngquant壓縮,輸出視覺判斷是否可行
(3)對assets中的圖片資源也使用aapt的crunch做圖片預處理,crunch有可能會使圖片變大,在這種情況,我們可以替換成原圖
需要注意的是對於.9.png,由於crunch過程中去除了黑邊,所以不能替換 並且.9圖是可調整大小的壓縮圖 不需要壓縮的

3 語言包壓縮
語言包動態載入 程式中繼承Resource實現getString方式讀取即可

4 外掛化
動態載入功能模組

5 SO檔案體積優化所以一般不可取
預設使用的壓縮方式是 ZIP 可以改成 LZMA方式壓縮
具體使用:
1 將SO檔案使用LZMA演算法進行壓縮放進Assets目錄下,並在程式第一次載入的時候解壓到應用的私有目錄
2 需要將所有的System.loadlibrary()方式呼叫改為 通過System.load(path)的方式呼叫,並將所有使用路徑載入或讀取so檔案的程式碼進行路徑的重新設定
(LZMA庫 本身只有39KB的大小) 一種7ZIP壓縮演算法
如果so檔案存在對其他檔案的依賴,或者被其他庫隱式地呼叫,使用這種方式壓縮會導致執行時錯誤


二、dex不超過65535個方法數 (線性分配)
一個DEX檔案中method個數採用使用原生型別short來索引檔案中的方法 即16位 (2^16 = 65536) 因此不能超過這個數

LinearAlloc問題的原因
安裝時會提示INSTALL_FAILED_DEXOPT
因為應用在安裝時,系統會通過dexopt來優化dex檔案,
在優化過程中dexopt採用一個固定大小的緩衝區LinearAlloc來儲存應用所有資訊,LinearAlloc緩衝區在新版本Android系統中預設大小是8MB或16MB,但在Android2.2和2.3中只有5M,當待安裝apk方法數較多時,
儘管方法數沒有達到65536,可能儲存空間超過上限,這種情況dexopt程式就會報錯,從而導致安裝失敗

檢視專案的dex方法數:
android-studio 有內建apk Analyzer工具 (Build->AnalyzeApk)
可以檢視apk大小 dex大小 dex方法數


解決以上問題:

多dex檔案方式
通過自定義類載入工具
一、
1 在defaultConfig中新增multiDexEnabled true
2
compile ‘com.android.support:multidex:1.0.0’
or
compile ‘org.robolectric:shadows-multidex:3.3.1’
3 Application,繼承MulitDexApplication 或者重寫 Application的attachBaseContext()

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);     
}

參考:
https://blog.csdn.net/S1107432915SL/article/details/51036816
https://developer.android.com/studio/build/multidex?utm_campaign=io16&utm_source=anddev&utm_medium=blog
http://blog.csdn.net/zylc369/article/details/44660007

二、
1 將 附加dex檔案從 asset resource 拷貝 到 應用儲存空間中
2 例項化 DexClassLoader to load the library from the extracted secondary dex file
至於要呼叫方法 可以
(1) 類例項被強制轉換為一個介面,通過該介面直接呼叫該方法
(2) 反射方式 但是該方式會降低效能
3 修改編譯指令碼
參考:https://android-developers.googleblog.com/2011/07/custom-class-loading-in-dalvik.html

外掛化方式: 參考:


線性記憶體(LinearAlloc)限制: 系統讀取dex資料時不超過 5-16M
解決:
1 FaceBook提供了一個修改系統線性記憶體的值 (但是相容性可能會有問題 因為直接改虛擬機器的屬性 如三星手機)
https://www.facebook.com/notes/facebook-engineering/under-the-hood-dalvik-patch-for-facebook-for-android/10151345597798920