AndriodAPK體積優(yōu)化

Andriod APK體積優(yōu)化

創(chuàng)新互聯(lián)憑借專業(yè)的設計團隊扎實的技術支持、優(yōu)質高效的服務意識和豐厚的資源優(yōu)勢,提供專業(yè)的網站策劃、成都做網站、網站制作、網站優(yōu)化、軟件開發(fā)、網站改版等服務,在成都十年的網站建設設計經驗,為成都數千家中小型企業(yè)策劃設計了網站。

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

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

下面是項目總常用的對apk進行優(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 進行移除,配合 //Zipalign優(yōu)化

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

關于混淆相關的配置,不是本文重點,下面進行簡單介紹

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 表示混淆時不使用大小寫混合類名。

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

-verbose 表示打印混淆的詳細信息。

-dontoptimize 表示不進行優(yōu)化,建議使用此選項,因為根據proguard-android-optimize.txt中的描述,

優(yōu)化可能會造成一些潛在風險,不能保證在所有版本的Dalvik上都正常運行

-dontpreverify 表示不進行預校驗。這個預校驗是作用在Java平臺上的,Android平臺上不需要這項功能,

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

-keepattributes Annotation 表示對注解中的參數進行保留。

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

大部分應用其實并不需要支持幾十種語言的國際化支持,比如國內應用只支持中文,配置如下:

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

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

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

lib

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

assets

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

res

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

classes.dex

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

META-INF

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

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

AndroidManifest.xml

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

rsources.arsc

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

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

so文件優(yōu)化

首先對lib文件夾進行瘦身:

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

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

armeabi/armeabi-v7a:這個架構是arm類型的,主要用于Android 4.0之后的,cpu是32位的,其中armeabi是相當老舊的一個版本, 缺少對浮點數的硬件支持,基本已經淘汰,可以不用考慮了。

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

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

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

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

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

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

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

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

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

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

res目錄優(yōu)化:

手動lint檢查,手動刪除無用的資源文件。

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

使用tinypng等圖片壓縮工具對圖片進行壓縮

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

Tinypng的官方網站:http://tinypng.com/

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

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

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

盡量少使用幀動畫,幀動畫需要的圖片較多,并且很占內存,建議使用屬性動畫替代。

使用一套資源

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

使用jpg格式

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

縮小大圖

如果經過上述步驟之后,你的工程里面還有一些大圖,考慮是否有必要維持這樣的大尺寸,是否能適當的縮小。

事實上,由于設計師出圖的原因,我們拿到的很多圖片完全可以適當的縮小而對視覺影響是極小的。

覆蓋第三庫里的大圖

有些第三庫里引用了一些大圖但是實際上并不會被我們用到,就可以考慮用1x1的透明圖片覆蓋。你可能會有點不舒服,因為你的drawable下竟然包含了一些莫名其妙的名稱的1x1圖片

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

矢量圖

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

優(yōu)勢

(1)占用存儲空間小

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

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

劣勢

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

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

(3) 不支持.9圖

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

實現(xiàn):

在app的build.graldle中的defaultConfig 標簽下:

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背景

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

使用著色方案

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

加上一行代碼 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"
?/>

AndriodAPK體積優(yōu)化
轉載來于:http://muchs.cn/article36/jepgsg.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供用戶體驗ChatGPT、Google營銷型網站建設、企業(yè)網站制作、建站公司

廣告

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

搜索引擎優(yōu)化