我們完成一個app后,都需要生成一個apk,然后上線,而apk的大小也一定程度的影響了用戶是否愿意下載你的這個app,所以也就有了apk瘦身這門藝術。
目錄
apk的結(jié)構
-
圖片壓縮
導入矢量圖
適配問題
Tint 著色器
-
動態(tài)庫移除
so庫的相關知識點
ABI
結(jié)束語
apk的結(jié)構
既然要對一個apk瘦身,首先我們就得知道apk格式的文件內(nèi)容。實際上一個apk文件就是一個zip包,我們只需要將后綴改為zip,然后進行解壓就可以看到里面的內(nèi)容了。下面我們來看下它里面的文件以及作用:
apk包含以下目錄:
assets/: 包含了應用的資源,這些資源能夠通過AssetManager對象獲得。lib/: 包含了針對處理器層面的被編譯的代碼。這個目錄針對每個平臺類型都有一個子目錄,比如armeabi, armeabi-v7a, arm64-v8a, x86, x86_64和mips。res/: 包含了沒被編譯到resources.arsc的資源。META-INF/: 包含CERT.SF和CERT.RSA簽名文件,也包含了MANIFEST.MF文件。(譯注:校驗這個APK是否被人改動過)
apk包含以下文件:
classes.dex: 包含了能被Dalvik/Art虛擬機理解的 dex 文件格式的類。resources.arsc: 包含了被編譯的資源。該文件包含了res/values目錄的所有配置的 xml 內(nèi)容。打包工具將 xml 內(nèi)容編譯成二進制形式并壓縮。這些內(nèi)容包含了語言字符串和styles,還包含了那些內(nèi)容雖然不直接存儲在resources.arsc文件中,但是給定了該內(nèi)容的路徑,比如布局文件和圖片。所以又叫 資源映射表AndroidManifest.xml: 包含了主要的Android配置文件。這個文件列出了應用名稱、版本、訪問權限、引用的庫文件。該文件使用二進制 xml 格式存儲。(譯注:該文件還能看到應用的minSdkVersion, targetSdkVersion等信息)
好的,現(xiàn)在我們已經(jīng)知道apk到底是個什么東東了,接下來我們開始一步步對這些內(nèi)容進行瘦身處理。
圖片壓縮
我們都知道,一個apk會使用大量的圖片,如果圖片這塊能夠壓縮下,那效果還是非??捎^的。
如下圖,我們在項目中經(jīng)常會用到這樣的套圖。

明明只是一種圖片,而我們卻因為大小和顏色,需要這樣的一組,顯然很占大小,那有沒有什么方式優(yōu)化下呢?
答案是有的。
谷歌的AS為我們提供了一個名為 Vector Asset Studio 的工具,可以幫助我們添加內(nèi)置Material圖標以及將本地的SVG(Scalable Vector Graphics 可縮放矢量圖)等格式作為矢量圖資源導入到項目中,會在drawable目錄下生成一個根節(jié)點為vector的xml文件,而且矢量圖的大小也更小,是不是非常棒??!那下面我們來看看怎么實現(xiàn)的。
導入矢量圖
首先我們在AS中運行Vector Asset Studio,步驟是:右鍵點擊你工程中的res文件夾,然后選擇 New --> Vector Asset,此時會彈出下面對話框,選擇圖中標記的對應操作即可導入內(nèi)置Material圖標或者SVG矢量圖。

但是上面這種方式只能一張張導入圖片,顯然很麻煩。那有沒有更好的方式了?實際上我們之所以要用這個工具導入svg圖片,而不是直接將svg圖片復制到drawable中,是因為安卓不支持svg,需要工具轉(zhuǎn)換下,所以我們可以使用svg2vector這個第三方庫進行批量轉(zhuǎn)換,然后直接復制到drawable中即可,轉(zhuǎn)換命令如下:
java -jar svg2vector-cli-1.0.0.jar -d . -o a -h 20 -w 20
-d 指定svg文件所在目錄 -o 輸出android vector圖像目錄 -h 設置轉(zhuǎn)換后svg的高 -w 設置轉(zhuǎn)換后svg的寬
適配問題
因為矢量圖是在Android 5.0(API21)才開始支持的,所以這個地方我們還需要適配下。如果不適配,你的最小minSdkVersion版本又小于21,則會自動在每個drawable目錄下生成對應的png圖片,反而會使apk包變大,所以這里一定要注意了。我們有下面兩種方式進行適配:
方式一:生成 png 格式的圖片
這種方式是在drawable文件中生成對應的png,不過我們可以指定只生成哪幾個。例如如下配置
我們可以在項目的build.gradle中進行如下配置,即可在指定的drawable文件中生成對應的png格式圖片。

方式二:支持庫
還一種方式就是使用支持庫,支持庫的版本需要23.2或者更高,也是在項目的build.gradle中進行配置,如下:

這種適配方式使用圖片的時候,需要用 app:srcCompat 屬性,而不是 android:src,如下:

通過這個方式只是解決了不同大小需要多張圖片的問題,但是還需要有不同顏色的圖片。這個我們怎么處理呢?不要急,這個問題谷歌工程師也為我們準備了一個工具,它就是Tint著色器。
Tint 著色器
一般我們矢量圖都是使用黑色,然后由Tint著色器去修改顏色,直接在xml中使用即可,如下:

在java代碼中,我們可以通過DrawableCompat去設置,如下:

那如果想要實現(xiàn)按鍵效果,通過 Tint 也能實現(xiàn)嗎?答案是可以的。
首先我們需要創(chuàng)建兩個選擇器,一個是 drawable 選擇器,一個是 color 選擇器,如下:


然后就可以直接使用了,如下:

總的來說使用Tint找色器去修改矢量圖的顏色還是蠻簡單的吧。
通過矢量圖這個方式,我們就能夠減小使用圖片的總大小,從而減小apk的大小。
瘦身不是一蹴而就的,所以我們接著減。
動態(tài)庫移除
so庫的相關知識點
說到so庫,相信大部分人都有使用過,但是卻不知道它到底是什么。其實so庫就是由ndk編譯出來的動態(tài)庫。
那我們?yōu)槭裁匆裺o文件分別放在armeabi、arm64-v8a、armeabi-v7a、x86、x86_64這些文件中呢?
主要是因為我們的app運行在不同的手機中,而so庫是由c\c++編譯的,不是跨平臺的,所以不同平臺(不同CPU)需要使用不同的so庫。那不同的文件是什么意思呢?我們接著往下看。
ABI
ABI 是應用程序二進制接口簡稱(Application Binary Interface),定義了二進制文件(尤其是.so文件)如何運行在相應的系統(tǒng)平臺上,從使用的指令集,內(nèi)存對齊到可用的系統(tǒng)函數(shù)庫。在Android 系統(tǒng)上,每一個CPU架構對應一個ABI,即:armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,mips,mips64。
ABI
Supported Instruction Set(s)
armeabi
ARMV5TE and later,Thumb-1
armeabi-v7a
armeabi,Thumb-2,VFPv3-D16,Other,optional
arm64-v8a
AArch-64
x86
x86(IA-32),MMX,SSE/2/3,SSSE3
x86_64
x86-64,MMX,SSE/2/3,SSE3,SSE4.1,SSE4.2,POPCNT
mips
MIPS32r1 and later
mips64
MIPS64r6
各版本分析如下:
mips / mips64:極少用于手機可以忽略
x86 / x86_64:x86 架構的手機都會包含由 Intel 提供的稱為 Houdini 的指令集動態(tài)轉(zhuǎn)碼工具,實現(xiàn) 對 arm .so 的兼容,再考慮 x86 1% 以下的市場占有率,x86 相關的兩個 .so 也是可以忽略的
armeabi:ARM v5 這是相當老舊的一個版本,缺少對浮點數(shù)計算的硬件支持,在需要大量計算時有性能瓶頸
armeabi-v7a:ARM v7 目前主流版本
arm64-v8a:64位支持
所以現(xiàn)在我們一般只要在項目的build.gradle中適配ARM v7就行了,如下:

結(jié)束語
好的,今天我們就暫時介紹到這兒,瘦身之旅長路漫漫,還有的方式我們下次分享。