AndriodAPK體積優(yōu)化-創(chuàng)新互聯(lián)

Andriod APK體積優(yōu)化

創(chuàng)新互聯(lián)作為成都網(wǎng)站建設(shè)公司,專注成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì),有關(guān)企業(yè)網(wǎng)站制作方案、改版、費(fèi)用等問題,行業(yè)涉及成都純水機(jī)等多個(gè)領(lǐng)域,已為上千家企業(yè)服務(wù),得到了客戶的尊重與認(rèn)可。

隨著項(xiàng)目的不斷迭代,功能越來越多,構(gòu)建出來的apk文件的大小也會(huì)越來越大,這樣會(huì)導(dǎo)致在移動(dòng)網(wǎng)絡(luò)情況下下載時(shí),使用的網(wǎng)絡(luò)流量會(huì)增大,并且apk太大,導(dǎo)致下載的時(shí)間也增加,雖然當(dāng)前每個(gè)人的手機(jī)的流量都很多,對用戶流量影響不大,但是據(jù)一些網(wǎng)站統(tǒng)計(jì),安裝包越大,用戶的轉(zhuǎn)化率是在降低的,所以減少apk的體積,可以讓更多的用戶愿意去下載和體驗(yàn)產(chǎn)品。所以,對apk體積進(jìn)行瘦身還是很有必要的。在對apk體積進(jìn)行瘦身前,最好保證這個(gè)apk已經(jīng)是經(jīng)過Proguard優(yōu)化過的。

經(jīng)過了Proguard對apk進(jìn)行壓縮,優(yōu)化,混淆后,在去對這個(gè)已經(jīng)進(jìn)行優(yōu)化過的apk進(jìn)行瘦身更有意義。

下面是項(xiàng)目總常用的對apk進(jìn)行優(yōu)化的方式:

在app的主module下的gradle文件中做如下配置

buildTypes?{
	release?{
		//開啟代碼混淆
		minifyEnabled?true
		//Zipalign優(yōu)化
		zipAlignEnabled?true
		//移除無用的resource文件
		shrinkResources?true
		proguardFiles?getDefaultProguardFile('proguard-android.txt'),?'proguard-rules.pro'
	}
}

使用 shrinkResources 進(jìn)行移除,配合 //Zipalign優(yōu)化

使用 shrinkResources 必須先開啟代碼混淆 minifyEnabled

關(guān)于混淆相關(guān)的配置,不是本文重點(diǎn),下面進(jìn)行簡單介紹

proguard-android.txt文件中的常用的混淆配置信息如下:

#?This?is?a?configuration?file?for?ProGuard.
#?http://proguard.sourceforge.net/index.html#manual/usage.html
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
#?Optimization?is?turned?off?by?default.?Dex?does?not?like?code?run
#?through?the?ProGuard?optimize?and?preverify?steps?(and?performs?some
#?of?these?optimizations?on?its?own).
-dontoptimize
-dontpreverify
#?Note?that?if?you?want?to?enable?optimization,?you?cannot?just
#?include?optimization?flags?in?your?own?project?configuration?file;
#?instead?you?will?need?to?point?to?the
#?"proguard-android-optimize.txt"?file?instead?of?this?one?from?your
#?project.properties?file.
-keepattributes?*Annotation*
-keep?public?class?com.google.vending.licensing.ILicensingService
-keep?public?class?com.android.vending.licensing.ILicensingService
#?For?native?methods,?see?http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames?class?*?{
?native?<methods>;
}
#?keep?setters?in?Views?so?that?animations?can?still?work.
#?see?http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers?public?class?*?extends?android.view.View?{
?void?set*(***);
?***?get*();
}
#?We?want?to?keep?methods?in?Activity?that?could?be?used?in?the?XML?attribute?onClick
-keepclassmembers?class?*?extends?android.app.Activity?{
?public?void?*(android.view.View);
}
#?For?enumeration?classes,?see?http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers?enum?*?{
?public?static?**[]?values();
?public?static?**?valueOf(java.lang.String);
}
-keepclassmembers?class?*?implements?android.os.Parcelable?{
?public?static?final?android.os.Parcelable$Creator?CREATOR;
}
-keepclassmembers?class?**.R$*?{
?public?static?<fields>;
}
#?The?support?library?contains?references?to?newer?platform?versions.
#?Dont?warn?about?those?in?case?this?app?is?linking?against?an?older
#?platform?version.?We?know?about?them,?and?they?are?safe.
-dontwarn?android.support.**

-dontusemixedcaseclassnames 表示混淆時(shí)不使用大小寫混合類名。

-dontskipnonpubliclibraryclasses 表示不跳過library中的非public的類。

-verbose 表示打印混淆的詳細(xì)信息。

-dontoptimize 表示不進(jìn)行優(yōu)化,建議使用此選項(xiàng),因?yàn)楦鶕?jù)proguard-android-optimize.txt中的描述,

優(yōu)化可能會(huì)造成一些潛在風(fēng)險(xiǎn),不能保證在所有版本的Dalvik上都正常運(yùn)行

-dontpreverify 表示不進(jìn)行預(yù)校驗(yàn)。這個(gè)預(yù)校驗(yàn)是作用在Java平臺(tái)上的,Android平臺(tái)上不需要這項(xiàng)功能,

去掉之后還可以加快混淆速度。

-keepattributes Annotation 表示對注解中的參數(shù)進(jìn)行保留。

更多關(guān)于proguard混淆規(guī)則的介紹,請參考Android安全***戰(zhàn),反編譯與混淆技術(shù)完全解析(下)

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

defaultConfig?{
?...
?//只保留指定和默認(rèn)的資源
?//resConfigs('zh-rCN','ko')
?resConfigs?"zh"
}

經(jīng)過上面的配置后,打包出的apk,在進(jìn)行apk的分析,這樣效果會(huì)更好。Android studio 從2.2開始就提供了分析apk文件的功能,在Android Studio工具欄里,打開build–>Analyze APK, 選擇要分析的APK包,或者直接將apk包拖到AS中。下圖是對apk分析的結(jié)果:

但是在看上面這個(gè)圖之前,需要先了解各個(gè)部分的含義:

lib

這個(gè)目錄存放應(yīng)用程序依賴的用C/C++ 編寫的 native 庫文件,該目錄下可以包含 3 種類型,根據(jù) CPU 類型的不同加載不同目錄下的 so 庫,這3種類型分別為 ARM 架構(gòu)、MIPS 架構(gòu)、 X86 架構(gòu)。所示,不同的 CPU 架構(gòu)設(shè)備在應(yīng)用程序運(yùn)行時(shí),根據(jù) CPU 架構(gòu)類型加載對應(yīng)的目錄,每個(gè)目錄可以存放很多對應(yīng)版本的 so 庫,同時(shí)這個(gè)目錄結(jié)構(gòu)固定,用戶必須嚴(yán)格按照這個(gè)目錄存放自己的 so文件。

assets

assets目錄可以根據(jù)應(yīng)用需求存放任何文件夾架構(gòu),如配置文件、資源文件(如 WebView本地資源、圖片資源等),這些文件的內(nèi)容在程序運(yùn)行過程中可以通過 AssetManager 類獲得。和 res 的不同點(diǎn)在于, res 目錄下的文件會(huì)在 .R 文件中生成對應(yīng)的資源 ID assets 不會(huì)自動(dòng)生成對應(yīng)的 ID ,而是通過 AssetMana ger 類的接口獲取。

res

res是 resource 的縮寫,這個(gè)目錄存放資源文件,在這個(gè)文件夾下的所有文件 都會(huì)生成對應(yīng)的 ID 映射到 Android 工程的 .R 文件中,訪問時(shí)可以直接使用資源。

classes.dex

Java可執(zhí)行程序,需要先把 Java 文件編譯成 class 文件,字節(jié)碼都保存在 class 文件中,Java 虛擬機(jī)可以通過解釋并執(zhí)行這些 class 文件。而 Dalvik 虛擬機(jī)在 Java 虛擬機(jī)進(jìn)行了優(yōu)化,執(zhí)行的是 Dalvik 字節(jié)碼,這些 Dalvik 字節(jié)碼由 Java 字節(jié)碼轉(zhuǎn)換而來,一般情況下, Android應(yīng)用在打包時(shí)通過 Android SDK 中的 dx 工具將 Java 字節(jié)碼轉(zhuǎn)換為 Dalvik 字節(jié)碼。 dx 工具可以對多個(gè) class 文件進(jìn)行合并重組、優(yōu)化,達(dá)到減小體積、縮短運(yùn)行時(shí)間的目的。

META-INF

保存應(yīng)用的簽名信息,簽名信息可以驗(yàn)證APK 文件的完整性。 Android SDK 在打包 APK時(shí)會(huì)計(jì)算 APK 包中所有文件的完整性,并且把這些完整性保存到 META-INF 文件夾下,應(yīng)用程序在安裝時(shí)首先根據(jù) META-INF 文件夾校驗(yàn) APK 的完整性,這樣可以保證 APK 中的每一個(gè)文件都不能被篡改。以此來確保 APK 應(yīng)用程序不被惡意修改或者病毒感染,有利于確保Android 應(yīng)用的完整性和系統(tǒng)的安全性。 META-INF目錄下包含的文件有 CERT.RSA 、 CERT.DSA 、CERT.SF 和 MANIFEST.MF ,其中 CERT.RSA 是開發(fā)者利用私鑰對 APK 進(jìn)行簽名的簽名文件,

CERT.SF 、 MANIFEST.MF 記錄了文件中文件的 SHA-1 哈希值。

AndroidManifest.xml

Android應(yīng)用程序的配置文件是用來描述 Android 應(yīng)用“整體資訊”的設(shè)定文件,簡單來說,相當(dāng)于 Android 應(yīng)用向 Android 系統(tǒng)“自我介紹”的配置文件。 Android 系統(tǒng)可以根據(jù)這個(gè)“自我介紹”完整地了解 APK 應(yīng)用程序的資訊,每個(gè) Android 應(yīng)用程序都必須包含一個(gè)AndroidManifest.xml 文件,且它的名字固定的,不能修改。在開發(fā) Android 應(yīng)用程序時(shí),一般都在 AndroidManifest.xml 中注冊代碼中的每個(gè) Activity 、 Service 、 Provider 和 Receiver ,只有這樣系統(tǒng)才能啟動(dòng)對應(yīng)的組件,另外這個(gè)文件還包含一些權(quán)限聲明以及使用的 SDK 版本信息等。

rsources.arsc

記錄資源文件和資源ID 之間的映射關(guān)系,用來根據(jù)資源 ID 尋找資源。 Android 的開發(fā)是分模塊的, res 目錄專門用來存放資源文件,在代碼中需要調(diào)用資源文件時(shí),只需要調(diào)用findviewbyId ()就可以得到資源文件,每當(dāng)在 res 文件夾下放一個(gè)文件, aapt 就會(huì)自動(dòng)生成對應(yīng)的 ID 保存在 .R 文 件中,調(diào)用這個(gè) ID 就可以,但是只有這個(gè) ID 還不夠, .R 文件只是保證編譯程序不報(bào)錯(cuò),實(shí)際上在程序運(yùn)行時(shí),系統(tǒng)要根據(jù) ID 尋找對應(yīng)的資源路徑,而resources.arsc 文件就是用來記錄這些 ID 和資源文件位置對應(yīng)關(guān)系的文件。

通過上圖中對apk文件中各個(gè)部分的文件占比的分析,可以看到占用空間的主要是代碼、圖片、資源和lib和assert文件,主要方向精簡代碼、壓縮圖片、去除無用的庫、減少asserts里面文件。

so文件優(yōu)化

首先對lib文件夾進(jìn)行瘦身:

lib文件夾中存放的都是so文件,so文件存放到不同的cpu架構(gòu)的文件夾中,之所以這樣處理,就需要了解so的編譯類型,Android只支持3種cpu架構(gòu)分為:arm,mips,x86,目前用的最多的是arm體系cpu,x86和mips體系的很少用到了。

arm體系中,又分32位和64位

armeabi/armeabi-v7a:這個(gè)架構(gòu)是arm類型的,主要用于Android 4.0之后的,cpu是32位的,其中armeabi是相當(dāng)老舊的一個(gè)版本, 缺少對浮點(diǎn)數(shù)的硬件支持,基本已經(jīng)淘汰,可以不用考慮了。

arm64-v8a:這個(gè)架構(gòu)是arm類型的,主要是用于Android 5.0之后,cpu是64位的。

平時(shí)項(xiàng)目中引入第三方的so文件時(shí),第三方會(huì)根據(jù)cpu的架構(gòu)編譯成不同類型的so文件,項(xiàng)目引入這些so文件時(shí),會(huì)將這些文件分別放入jniLibs目錄下的arm64-v8a,armeabi-v7a等這些目錄下,其實(shí)對于arm體系的so文件,沒這個(gè)必要,因?yàn)閍rm體系是向下兼容的,比如32位的so文件是可以在64位的系統(tǒng)上運(yùn)行的。Android上每啟動(dòng)一個(gè)app都會(huì)創(chuàng)建一個(gè)虛擬機(jī),Android 64位的系統(tǒng)加載32位的so文件時(shí),會(huì)創(chuàng)建一個(gè)64位的虛擬機(jī)的同時(shí),還會(huì)創(chuàng)建一個(gè)32位的虛擬機(jī),這樣就能兼容32位的app應(yīng)用了。鑒于兼容的原理,在app中,可以只保留armeabi-v7a版本的so文件就足夠了。64位的操作系統(tǒng)會(huì)在32位的虛擬機(jī)上加載這個(gè)它。這樣就極大的精簡了app打包后的體積。

雖然這樣可以精簡apk的體積,但是,在64位平臺(tái)上運(yùn)行32位版本的ART和Android組件,將丟失專為64位優(yōu)化過的性能(ART,webview,media等等)所以,更好的方法是,為相應(yīng)的abi打?qū)?yīng)的apk包,這樣就可以為不同abi版本生成不同的apk包。

所以可以通過如下配置,只保留armeabi-v7a版本的so文件在module的build.gradle文件中defaultConfig節(jié)點(diǎn)做下面的配置:

?```
	//配置so庫架構(gòu)(真機(jī):?arm?,模擬器?x86?)
	defaultConfig?{
?		...
?		ndk?{
?		?//abiFilters?"armeabi",?"armeabi-v7a"
?		abiFilters?'armeabi-v7a'
?		?}
	?}
	```
	完成這個(gè)步驟后,就可以看到,apk包中的lib中,只剩下armeabi-v7a文件夾中的so文件了。

重新編譯so文件,用更小的庫代替

很多第三方我們導(dǎo)入進(jìn)來只用到其中很小一部分功能,大部分功能都是我們用不上的。這時(shí)候我們找到源代碼,將我們需要的那部分代碼提取出來,重新編譯成新的so文件,再導(dǎo)入到我們項(xiàng)目中。

通過插件化,動(dòng)態(tài)加載so庫文件。

assets目錄中的優(yōu)化

如果存放的資源文件實(shí)在太大,可以考慮將部分不是立刻用到的資源文件,從網(wǎng)絡(luò)上下載到本地。這樣也能夠減少asstes目錄的大小。

res目錄優(yōu)化:

手動(dòng)lint檢查,手動(dòng)刪除無用的資源文件。

版本迭代過程中,不但有廢棄代碼冗余,肯定會(huì)有無用的圖片存在。在build.gradle 里面配置shrinkResources true,在打包的時(shí)候會(huì)自動(dòng)清除掉無用的資源,但經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn)打出的包并不會(huì),而是會(huì)把部分無用資源用更小的東西代替掉。注意,這里的“無用”是指調(diào)用圖片的所有父級函數(shù)最終是廢棄代碼,而shrinkResources true 只能去除沒有任何父函數(shù)調(diào)用的情況,真正起效果只能通過Android Studio自帶的 “Remove Unused Resources”小插件來實(shí)現(xiàn)了。更人性化是該查找結(jié)果可以“一鍵刪除”。當(dāng)然,可能圖片是經(jīng)過反射或字符拼接等方式獲取,所以這個(gè)檢測列表也不是全對,刪除后很大概率編譯失敗或部分頁面掛死、無圖等問題,這個(gè)無解,工具還沒智能到這個(gè)地步,你只能一遍又一遍“編譯—解決部分問題—再編譯再”。

使用tinypng等圖片壓縮工具對圖片進(jìn)行壓縮

TinyPNG工具只支持上傳PNG圖片到官網(wǎng)上壓縮,然后下載保存,在保持alpha通道的情況下對PNG的壓縮可以達(dá)到1/3之內(nèi),而且用肉眼基本上分辨不出壓縮的損失.。

Tinypng的官方網(wǎng)站:http://tinypng.com/

大部分的圖片使用webp格式替代

webp支持透明度,壓縮比比jpg更高但顯示效果卻不輸于jpg,官方評測quality參數(shù)等于75均衡最佳。相對于jpg、png,webp作為一種新的圖片格式,限于android的支持情況暫時(shí)還沒用在手機(jī)端廣泛應(yīng)用起來。從Android 4.0+開始原生支持,但是不支持包含透明度,直到Android 4.2.1+才支持顯示含透明度的webp,使用的時(shí)候要特別注意。

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

盡量少使用幀動(dòng)畫,幀動(dòng)畫需要的圖片較多,并且很占內(nèi)存,建議使用屬性動(dòng)畫替代。

使用一套資源

對于絕大對數(shù)APP來說,只需要取一套設(shè)計(jì)圖就足夠了。鑒于現(xiàn)在分辨率的趨勢,建議取1080p的資源,放到xxhdpi目錄,在加上一些屏幕適配的處理,基本能夠適配大部分的手機(jī)。相對于多套資源,只使用1080P的一套資源,在視覺上差別不大,很多大公司的產(chǎn)品也是如此,但卻能顯著的減少資源占用大小,順便也能減輕設(shè)計(jì)師的出圖工作量了。

使用jpg格式

如果對于非透明的大圖,jpg將會(huì)比png的大小有顯著的優(yōu)勢,雖然不是絕對的,但是通常會(huì)減小到一半都不止。在啟動(dòng)頁,活動(dòng)頁等之類的大圖展示區(qū)采用jpg將是非常明智的選擇。

縮小大圖

如果經(jīng)過上述步驟之后,你的工程里面還有一些大圖,考慮是否有必要維持這樣的大尺寸,是否能適當(dāng)?shù)目s小。

事實(shí)上,由于設(shè)計(jì)師出圖的原因,我們拿到的很多圖片完全可以適當(dāng)?shù)目s小而對視覺影響是極小的。

覆蓋第三庫里的大圖

有些第三庫里引用了一些大圖但是實(shí)際上并不會(huì)被我們用到,就可以考慮用1x1的透明圖片覆蓋。你可能會(huì)有點(diǎn)不舒服,因?yàn)槟愕膁rawable下竟然包含了一些莫名其妙的名稱的1x1圖片

使用微信資源壓縮打包工具(AndResGuard)

矢量圖

矢量圖是由點(diǎn)與線組成,和位圖不一樣,它再放大也能保持清晰度,而且使用矢量圖比位圖設(shè)計(jì)方案能節(jié)約30~40%的空間,現(xiàn)在谷歌一直在強(qiáng)調(diào)扁平化方式,矢量圖可很好的契合該設(shè)計(jì)理念。

優(yōu)勢

(1)占用存儲(chǔ)空間小

(2) 無極拉伸不會(huì)出現(xiàn)鋸齒,可以照顧不同尺寸的機(jī)型

(3)Android Studio自帶很多資源,減小UI工作量

劣勢

(1) 只支持5.0及以上系統(tǒng)

(2) 與位圖相比多了一層計(jì)算,需消耗更多性能

(3) 不支持.9圖

(4)不適合表現(xiàn)真實(shí)照片和復(fù)雜圖形,一般使用在簡單的icon和動(dòng)畫上

實(shí)現(xiàn):

在app的build.graldle中的defaultConfig 標(biāo)簽下:

defaultConfig?{
	minSdkVersion?19
	targetSdkVersion?28
	versionCode?1
	versionName?"1.0"
	testInstrumentationRunner?"android.support.test.runner.AndroidJUnitRunner"
	//minSdkVersion?19?(5.0)
	vectorDrawables.generatedDensities('xhdpi','xxhdpi','xxxhdpi')
	//minSdkVersion?>?19
	//?vectorDrawables.useSupportLibrary?=?true
?}

使用shape背景

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

使用著色方案

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

加上一行代碼 android:tint="@color/colorAccent"

?<ImageView
?		android:layout_marginTop="100dp"
?		android:layout_gravity="center_horizontal"
?		android:layout_centerInParent="true"
?		android:src="@drawable/ic_icon_name"
?		android:layout_width="wrap_content"
	?android:layout_height="wrap_content"
?		android:tint="@color/colorAccent"
?/>

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

名稱欄目:AndriodAPK體積優(yōu)化-創(chuàng)新互聯(lián)
當(dāng)前URL:http://muchs.cn/article32/eeepc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站關(guān)鍵詞優(yōu)化、微信公眾號(hào)定制開發(fā)、移動(dòng)網(wǎng)站建設(shè)外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營