優(yōu)化apk大小

  1. APK的組成結(jié)構(gòu)

META-INF:包含CERT.SF和CERT.RSA簽名文件,和MANIFEST.MF清單文件。

assets:包含APP的assets資源,代碼中可以通過AssetManager對象訪問。

res:包含沒有編譯到resources.arsc中的資源。

lib:包含為特定處理器編譯的代碼。這個目錄包含不同平臺類型的子目錄,如armeabi,armeabi-v7a,arm64-v8a,x86,x86_64和mips。

resources.arsc:包含被編譯的資源。這個文件包含來自res/values目錄下所有配置的XML內(nèi)容。打包工具提取XML內(nèi)容,將它們編譯為二進(jìn)制的形式,并且打包。這些內(nèi)容包含語言字符串和樣式,和在resources.arsc文件不包含的內(nèi)容的路徑,如布局文件和圖片。

classes.dex:包含被編譯的類,以DalvikART虛擬機(jī)能理解的dex文件格式。

AndroidManifest.xml:核心的Android清單文件。這個文件羅列了APP名稱,版本,訪問權(quán)限,和APP引用的庫文件。這個文件使用Android的二進(jìn)制XML格式。

  1. 減小APK的大小的方式匯總

2.1 Lint工具

在Android Studio中的一個靜態(tài)代碼工具lint,檢測在你的res目錄下代碼沒有引用的資源,并沒有掃描assets目錄下的資源。當(dāng)lint工具在你的項目中發(fā)現(xiàn)一個潛在的未使用的資源,它會打印一條如下示例的消息。只提醒,不主動移除。

res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources]

2.2 ShrinkResourcesGradle以及MinifyEnabled

添加到代碼中的庫可能包含未使用的資源。在APP的build.gradle文件中啟動shrinkResourcesGradle,它能自動替你刪除這些資源。

android{   
    buildTypes{   
        release{   
            minifyEnabled true   
            shrinkResources true   
            proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'   
       }   
   }   
}   

為了使用shrinkResources,你必須啟動代碼壓縮,將minifyEnabled設(shè)置為true。在構(gòu)建的過程中,首先ProGuard會移除沒有使用的代碼,接著Gradle會移除沒有使用的資源。

在Proguard中,是否保留符號表對APP的大小是有顯著的影響的,可酌情注釋下面這行代碼,但是建議盡量保留,它可以用于保留調(diào)試信息。

-keepattributes SourceFile,LineNumberTable  

2.3 使用一套資源

對于絕大對數(shù)APP來說,只需要取一套設(shè)計圖就足夠了。鑒于現(xiàn)在分辨率的趨勢,建議取720p的資源,放到xhdpi目錄。在視覺上差別不大,很多大公司的產(chǎn)品也是如此,但卻能顯著的減少資源占用大小,這里不是說把非xhdpi的目錄都刪除,而是強(qiáng)調(diào)保留一套設(shè)計資源就夠了。

2.4 只保留中文的語言資源

大部分應(yīng)用其實并不需要支持幾十種語言的國際化支持。強(qiáng)大的gradle支持語言的配置,比如國內(nèi)應(yīng)用只支持中文:

android {  
    defaultConfig {  
        resConfigs "zh"  
    }  
}  

2.5 關(guān)于PNG圖片和JPG圖片

Android打包本身會對png進(jìn)行無損壓縮, TinyPNG使用智能有損壓縮技術(shù),在盡量少的損失下來減少PNG文件的大小。具體TinyPNG的信息請訪問https://tinypng.com/。

如果對于非透明的大圖,jpg將會比png的大小有顯著的優(yōu)勢,雖然不是絕對的,但是通常會減小到一半都不止。

在啟動頁,活動頁等之類的大圖展示區(qū)采用jpg將是非常明智的選擇。

當(dāng)然大圖適當(dāng)縮小對視覺的影響也不大,適當(dāng)縮小大圖也是可行的。

但是Android的界面能用png最好是用png,因為32位的png顏色過渡平滑且支持透明。jpg是像素化壓縮過的圖片,質(zhì)量已經(jīng)下降了,再拿來做9path的按鈕和平鋪拉伸的控件必然慘不忍睹,要盡量避免。

在res下這些icon用的都是png格式,就是說Google推薦使用的是png格式的圖片。

2.6 關(guān)于WEBP圖片

相對于jpg、png,webp作為一種新的圖片格式,壓縮比比jpg更高但顯示效果卻不輸于jpg,Android 4.0+才原生支持webp, 但是我們的app是兼容2.3+,所以4.0以下的設(shè)備將無法看到圖片但不會崩潰。限于Android的支持情況暫時還沒用在手機(jī)端廣泛應(yīng)用起來。并且直到Android 4.2.1+才支持顯示含透明度的webp,官方評測quality參數(shù)等于75均衡最佳。

官方介紹: https://developers.google.com/speed/webp/docs/precompiled

2.7 覆蓋某些圖片

一些aar庫里面包含根本就沒有用的圖。最典型的是support-v4兼容庫中包含一些“可能”用到的圖片,實際上在你的app中不會用到??梢钥紤]把幾張大一些的圖用1×1的圖片替換,如果9patch圖的話,要做成3×3的9patch圖替換。

同理可用于覆蓋第三方庫中我們用不到的大圖,可以在/build/intermediates/exploded-aar/下的各個aar庫的res目錄查找檢驗。

2.8 刪除armable-v7和x86包下的so

基本上armable的so也是兼容armable-v7的,armable-v7a的庫會對圖形渲染方面有很大的改進(jìn),如果沒有這方面的要求,可以精簡。這里不排除有極少數(shù)設(shè)備會Crash,請務(wù)必測試周全后再發(fā)布。

x86包下的so在x86型號的手機(jī)是需要的,如果產(chǎn)品沒用這方面的要求也可以精簡。

建議實際工作的配置是只保留armable、armable-x86下的so文件,算是一個折中的方案。

我們可以構(gòu)建一個 APK,它支持所有的 CPU 類型。但是反過來,我們可以為每個 CPU 類型都單獨構(gòu)建一個 APK,然后不同 CPU 類型的設(shè)備安裝對應(yīng)的 APK 即可,當(dāng)然前提是應(yīng)用市場得提供用戶設(shè)備 CPU 類型設(shè)別的支持,就目前來說,至少 PLAY 市場是支持的。
Gradle 可以通過以下配置生成不同 ABI 支持的 APK(引用自別的文章,沒實際使用過):

android {  
    ...  
    splits {  
        abi {  
            enable true  
            reset()  
            include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' //select ABIs to build APKs for  
            universalApk true //generate an additional APK that contains all the ABIs  
        }  
    }  
    // map for the version code  
    project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]  
    android.applicationVariants.all { variant ->  
        // assign different version code for each output  
        variant.outputs.each { output ->  
            output.versionCodeOverride =  
                    project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode  
        }  
    }  
 }  

2.9****微信資源壓縮打包

微信中的資源混淆工具主要為了混淆資源ID長度(例如將res/drawable/welcome.png混淆為r/s/a.png),同時利用7zip深度壓縮,大大減少了安裝包體積,同時也增加了逼格,提升了反破解難度。效果非常的好,強(qiáng)烈推薦。

具體實現(xiàn)原理請查看:http://www.iteye.com/topic/1141990

具體使用請查看:https://github.com/shwenzhang/AndResGuard

2.10 著色方案以及使用shape背景

相信你的工程里也有很多selector文件,也有很多相似的圖片只是顏色不同,通過著色方案我們能大大減輕這樣的工作量,減少這樣的文件。借助于androidsupport庫可實現(xiàn)一個全版本兼容的著色方案。

具體實現(xiàn)原理請查看:http://www.race604.com/tint-drawable/

在扁平化盛行的當(dāng)下,很多純色的漸變的圓角的圖片都可以用shape實現(xiàn),代碼靈活可控,省去了大量的背景圖片。

2.11 插件化

插件化技術(shù)支持動態(tài)的加載代碼和動態(tài)的加載資源,把APP的一部分分離出來了,對于業(yè)務(wù)龐大的項目來說非常有用,極大的分解了APP大小。因為插件化技術(shù)需要一定的技術(shù)保障和服務(wù)端系統(tǒng)支持,有一定的風(fēng)險,如無必要(比如一些小型項目,也沒什么擴(kuò)展業(yè)務(wù))就不需要了,建議酌情選擇。

2.12 資源的重用

同一個圖片的著色,陰影,或者旋轉(zhuǎn)版本等等,可以重用同一個資源集合和定制它們。

比如避免幀動畫的使用就是一個很好的例子(因為幀動畫每一幀都必須是一張明確的圖片文件)。

2.13 矢量圖的使用

矢量圖在Android中以VectorDrawable對象代表(Android L版本引入)。使用VectorDrawable對象,允許開發(fā)人員以純代碼方式生成類似繪制的效果。一個100-byte文件可以生成一個屏幕大小清晰圖像。

然而,每個VectorDrawable對象的渲染明顯的消耗系統(tǒng)時間,并且更大的圖片需要更長的時間來展示在屏幕上。因此僅僅在顯示小的圖片的時候考慮使用矢量圖。

具體使用請查看:http://mobile.51cto.com/news-478709.htm

2.14 移除枚舉

一個枚舉會增加你的app的class.dex文件大約1.0到1.4K的大小。對于復(fù)雜的系統(tǒng)或者共享庫這種情況會更加明顯。如果可能的話,考慮使用@IntDef和ProGuard來剝離枚舉,并轉(zhuǎn)換成Integer。這種類型轉(zhuǎn)換保留了所有枚舉的安全效益。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容