- 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格式。
- 減小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)換保留了所有枚舉的安全效益。