目錄
1.App為何臃腫?
Android出現的最初幾年裡很少有幾十兆的APP,但是現在我們卻發現幾十兆的應用比比皆是,出現這種情況的原因主要有以下三種:
Android碎片化的發展使得dpi的分類越來越多,從最初的ldpi、mdpi、hdpi到後來的xhdpi、xxhdpi、xxxhdpi、tvdpi等。
過多的引入第三方的函式庫和SDK,不可避免的多了一些重複的程式碼及資原始檔。
使用者對APP視覺要求的不斷提高,APP提供的資源細節越來越豐富,佔用的體積不斷上升。
2.APP的體積優化
根據APP臃腫的原因我們對APP的體積優化也主要是圍繞以上三個方面來進行的。
2.1圖片資源的優化
2.11 Android中使用的圖片格式
在介紹優化圖片資源之前我們先來了解下Android中的圖片格式。
/**
* Specifies the known formats a bitmap can be compressed into
*/
public enum CompressFormat {
JPEG (0),
PNG (1),
WEBP (2);
CompressFormat(int nativeInt) {
this.nativeInt = nativeInt;
}
final int nativeInt;
}
複製程式碼
通過檢視Bitmap的原始碼,我們可以發現Android中支援的編碼格式有JPEG、PNG、WEBP三種。另外我們還可以通過引入第三方函式庫實現對GIF的支援,接下來分別介紹一下這四種格式的特性。
JPEG:是一種廣泛使用的有失真壓縮影像的標準格式,它不支援透明和多幀動畫,一般影視類作品最終都是以JPEG格式展示。通過控制壓縮比,可以調整圖片大小。
PNG:PNG是一種無失真壓縮格式,它支援完整的透明通道,從影像處理領域講,JPEG只有RGB三個通道,而PNG有ARGB四個通道。由於是無失真壓縮因此PNG圖片一般佔用空間比較大,會無形中增加APP大小,所以我們在為APP瘦身時一般都要對PNG圖片進行處理以降低其大小。
GIF:誕生於1987年,特點是支援多幀動畫,社交平臺上的各種動態表情大部分是基於GIF來實現的。
WebP:由Google在2010年釋出的,它支援有損無失真壓縮、支援完整的透明通道、也支援多針動畫,是一種比較理想的圖片格式。目前國內像微信淘寶等都已經應用了WebP,所以在既保證圖片質量又限制圖片大小的情況下WebP應該是首選。
2.12 優化圖片資源
現如今我們在搭建APP介面的時候幾乎都是使用PNG格式的圖片,所以接下來會介紹幾個對PNG進行壓縮或修改的工具。
無失真壓縮:ImageOptim
ImageOptim是一個無損的壓縮工具,它通過優化PNG的壓縮引數,移除冗餘後設資料以及非必須的顏色配置檔案等方式,在不犧牲圖片質量的前提下,既減少了PNG圖片佔用的空間,又提高了載入速度。有失真壓縮:ImageAlpha
ImageAlpha是ImageOptim作者的一個有損的PNG壓縮工具,相比較而言,圖片的大小得到極大的減低,當然同時圖片的質量也會受到一定程度的影響,經過該工具壓縮的圖片,需要經過設計師的檢驗才能最終上線,否則可能會影響到整個APP的視覺效果。有失真壓縮:TinyPNG
TinyPNG也是比較知名的有損PNG壓縮工具,它以Web站點的形式提供,同所有的有失真壓縮工具一樣經過壓縮後的圖片需要經過設計師的檢驗才能上線。PNG/JPEG轉換為WebP
經過Google的測試無失真壓縮呢後的WebP比PNG檔案少了45%的檔案大小,即使這些PNG檔案經過其他無失真壓縮工具的壓縮後,WebP依然可以減少約28%的檔案大小。不過需要注意的是在Android4.0之上如果想要支援WebP需要整合第三方函式庫如:webp-android-backport來實現對WebP的支援。另外對於具有Alpha通道的PNG圖片來說,如果需要在Android4.2.1之前的系統上執行,那麼不能轉換成WebP格式因為只有在Android 4.2.1以上的系統中,才能解析具有Aplha通道的WebP圖片。WebP轉換工具可以選擇智圖和iSparta等。儘量使用NinePath格式格式的PNG圖片
.9.png圖片格式簡稱NinePath圖,它是針對Android平臺的一種特殊格式的PNG圖片格式,可以在圖片指定的位置拉伸或者填充內容。NinePath的優點是體積小、拉伸不變形、能夠很好的適配Android機型。Android Studio中自帶了NinePath圖的編輯工具,右鍵圖片選擇Create 9-Patch file即可建立.9.png圖片。
2.2 使用Android Lint刪除無用資源
Proguard只會對Java程式碼起作用,對於res/drawable/* 目錄中的圖片如果沒有使用到,Proguard只會移除該圖片在R檔案中的引用,不會刪除該圖片。這時就需要用到Android Lint。Android Lint整合在Android Studio中,它會分析res目錄下的資原始檔,但不會分析assets目錄下的資原始檔。
當然我們不能過度依賴工具還要人工確認是否真的多餘,例如某些資源是通過Java反射機制來使用的,這時Android Lint還是會檢測出資源沒有使用到。
2.3 利用Android Gradle配置
在Android Studio中我們可以通過配置app/build.gradle來進一步縮減App的大小。
- minifyEnable:
標識是否開啟Proguard混淆,設定為true時需要同時設定Proguard配置檔名和規則,Proguard的作用不僅僅是混淆,它還具有壓縮、優化等功能。它會遍歷所有程式碼並找出沒有引用到的程式碼,這些無用程式碼在生成最終Apk檔案之前會被過濾掉。
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
複製程式碼
- shrinkResources:
用來去除無用的resource檔案,shrinkResources必須在minifyEnable為true的時候才能起作用。
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
複製程式碼
同時shrinkResources也需要慎重使用,因為某些資源可能是通過反射機制獲取的,這類資源也可能會被過濾掉從而會導致在執行應用的時候會報Resource$NotFoundException異常,為了防止這種情況,可以在res/raw/下的一個叫keep.xml的檔案中定義這些例外,一個簡單的keep.xml的檔案如下:
xml<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/keep_me,@layout/main_*"/>
複製程式碼
- resConfigs:
在開發中不可避免的會引入第三方函式庫或者SDK,在不修改它們的前提下,不可避免的會引入很多我們不需要的資源,主要可以分為以下兩種:
1). DPI目錄:
由於Android支援的螢幕密度很多,所以我們可以根據自身需求剔除第三方函式庫或者SDK中不需要的DPI目錄或者檔案。
2). 國際化檔案:
我們引入的第三方函式庫可能做了國際化適配,所以我們可以根據自身的APP的需求來將我們不需要的國際化檔案給剔除掉。
android {
...
defaultConfig {
...
resConfigs "en","da","nl"
resConfigs "hdpi","xhdpi","xxhdpi","xxxhdpi"
}
複製程式碼
- ndk.abiFilters:
在app/bulid.gradle檔案中增加ndk.abiFilters配置,可以指定我們需要的ABI型別,從而可以過濾掉不需要的ABI型別的.so檔案。
android {
...
defaultConfig {
...
ndk{
abiFilters "armeabi-v7a" ,"x86"
}
}
複製程式碼
2.4 利用微信的資源混淆
微信資源混淆是通過直接修改resources.arsc檔案達到資原始檔名的混淆,同時利用7z深度壓縮,大大減少了安裝包體積,同時也增加了逼格,提升了反破解難度。