日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

你必须要懂的APK瘦身知识

發(fā)布時(shí)間:2023/12/9 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你必须要懂的APK瘦身知识 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

隨著業(yè)務(wù)復(fù)雜度的逐漸增加,代碼、資源也在不斷的增加,此時(shí)你的APP大小也在增加。從用戶層面來說,面對(duì)動(dòng)輒幾十兆的APP來說在非WIFI情況下還是會(huì)猶豫要不要下載,不下載你就可能因此失去了一個(gè)用戶。從公司層面來講,流量就是錢,減少APP的大小就顯得尤為重要。從開發(fā)者層面上來講,你掌握了這個(gè)手藝也會(huì)略顯逼格滿滿。

廢話不多說了,開始正題。

01 APK結(jié)構(gòu)的那些事

知己知彼,方能百戰(zhàn)不殆。了解應(yīng)用程序APK的結(jié)構(gòu)對(duì)于我們來說很有幫助。APK文件由一個(gè)ZIP存檔組成,其中包含組成應(yīng)用程序的所有文件。這些文件包括Java類文件,資源文件和包含編譯資源的文件。

APK包含以下目錄:

  • META-INF/:包含CERT.SF和 CERT.RSA簽名文件以及MANIFEST.MF 清單文件。
  • assets/:包含應(yīng)用可以使用AssetManager對(duì)象檢索的應(yīng)用資源。
  • res/:包含未編譯到的資源 resources.arsc。
  • lib/:包含特定于處理器軟件層的編譯代碼。該目錄包含了每種平臺(tái)的子目錄,像armeabi,armeabi-v7a, arm64-v8a,x86,x86_64,和mips。
  • resources.arsc:包含已編譯的資源。該文件包含res/values/ 文件夾所有配置中的XML內(nèi)容。打包工具提取此XML內(nèi)容,將其編譯為二進(jìn)制格式,并將內(nèi)容歸檔。此內(nèi)容包括語言字符串和樣式,以及直接包含在resources.arsc文件中的內(nèi)容路徑 ,例如布局文件和圖像。
  • classes.dex:包含以Dalvik / ART虛擬機(jī)可理解的DEX文件格式編譯的類。
  • AndroidManifest.xml:包含核心Android清單文件。該文件列出應(yīng)用程序的名稱,版本,訪問權(quán)限和引用的庫(kù)文件。該文件使用Android的二進(jìn)制XML格式。

來看看淘寶APP的unzip之后的文件目錄

taobao_app.png
一般來講APK結(jié)構(gòu)中比較大的部分一般是classes.dex、lib、res、assets這些文件或者目錄。所以接下來將會(huì)針對(duì)這四種情況進(jìn)行講解。

?

另外,我們通過APK Analyser 可以分析 APK


APK Analyser.png

02 減小 classes.dex

classes.dex 包含了所有 Java 代碼。當(dāng)你編譯你的應(yīng)用時(shí),gradle 會(huì)將你的所有模塊里的 .class 文件轉(zhuǎn)換成 .dex 文件并將這些文件合成一個(gè) classes.dex 文件。

單個(gè)的 classes.dex 文件可以容納大約 64K 方法。如果你達(dá)到了這個(gè)限制,你必須要在你的工程中啟用 multidexing。這將會(huì)創(chuàng)建另一個(gè) classes1.dex 文件去存儲(chǔ)剩下的方法。所以 classes.dex 文件數(shù)目由你的方法數(shù)而定。

減少第三庫(kù)的使用

隨著業(yè)務(wù)的頻繁變更以及復(fù)雜度的增加,我們往往會(huì)使用第三方Libaray,有時(shí)候我們可能僅僅用到了很少一部分的功能,這個(gè)時(shí)候就需要慎重考慮完全引用。從我的開發(fā)經(jīng)驗(yàn)上來講,寧愿參照自己去實(shí)現(xiàn),也不愿意多引入一個(gè)第三方庫(kù)。

避免枚舉

一個(gè)枚舉可以為您的應(yīng)用程序的classes.dex文件添加大約1.0到1.4 KB的大小 。這些添加可以快速累積到復(fù)雜系統(tǒng)或共享庫(kù)。如果可能,請(qǐng)考慮使用@IntDef注釋,這種類型轉(zhuǎn)換保留了枚舉的所有類型安全優(yōu)勢(shì)。

使用ProGuard

下面這段來自 build.gradle 文件的代碼用于為發(fā)布構(gòu)建啟用代碼壓縮:

android {buildTypes {release {minifyEnabled trueproguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'}}... }

?

除了 minifyEnabled 屬性外,還有用于定義 ProGuard 規(guī)則的 proguardFiles 屬性:

getDefaultProguardFile('proguard-android.txt') 方法可從 Android SDK tools/proguard/ 文件夾獲取默認(rèn)的 ProGuard 設(shè)置。
提示:要想做進(jìn)一步的代碼壓縮,請(qǐng)嘗試使用位于同一位置的 proguard-android-optimize.txt 文件。它包括相同的 ProGuard 規(guī)則,但還包括其他在字節(jié)碼一級(jí)(方法內(nèi)和方法間)執(zhí)行分析的優(yōu)化,以進(jìn)一步減小 APK 大小和幫助提高其運(yùn)行速度。

proguard-rules.pro 文件用于添加自定義 ProGuard 規(guī)則。默認(rèn)情況下,該文件位于模塊根目錄(build.gradle 文件旁)。

03 優(yōu)化assets和res中的資源文件

題外話

res/raw和assets的相同點(diǎn):

  • 兩者目錄下的文件在打包后會(huì)原封不動(dòng)的保存在apk包中,不會(huì)被編譯成二進(jìn)制。
  • res/raw和assets的不同點(diǎn):

  • res/raw中的文件會(huì)被映射到R.java文件中,訪問的時(shí)候直接使用資源ID即R.id.filename;assets文件夾下的文件不會(huì)被映射到R.java中,訪問的時(shí)候需要AssetManager類。
  • res/raw不可以有目錄結(jié)構(gòu),而assets則可以有目錄結(jié)構(gòu),也就是assets目錄下可以再建立文件夾。
  • 針對(duì)不同的情況,對(duì)于資源文件有不同的優(yōu)化策略。一般來講,對(duì)于res/drawable-**ddpi中的png資源可以進(jìn)行壓縮。

    圖片資源優(yōu)化策略

    格式壓縮

    使用TinyPng或者Guetzli進(jìn)行壓縮。Guetzli的使用可以參見我之前寫的博文在Mac上使用Google圖片壓縮工具Guetzli

    使用WebP文件格式

    定位Android 3.2(API級(jí)別13)或更高級(jí)別時(shí) ,您也可以使用WebP文件格式來制作圖像,而不是使用PNG或JPEG文件。WebP格式提供有損壓縮(如JPEG)以及透明度(如PNG),但可以提供比JPEG或PNG更好的壓縮。

    Android 4.0 (API level 14) 支持有損壓縮的WebP格式,Android 4.3 (API level 18) 開始支持無損透明WebP圖像。

    看下圖:


    webp_compress_performance.png

    壓縮效率極高,僅為PNG格式的12%。驚喜不驚喜。。。

    使用矢量圖形

    您可以使用矢量圖形來創(chuàng)建與分辨率無關(guān)的圖標(biāo)和其他可伸縮媒體。使用這些圖形可以大大減少您的APK足跡。矢量圖像在Android中表示為VectorDrawable對(duì)象。通過一個(gè)VectorDrawable對(duì)象,一個(gè)100字節(jié)的文件可以生成一個(gè)與屏幕尺寸一致的清晰圖像。

    但是,系統(tǒng)渲染每個(gè) VectorDrawable對(duì)象需要很長(zhǎng)時(shí)間,而較大的圖像需要更長(zhǎng)的時(shí)間才能顯示在屏幕上。因此,只有在顯示小圖像時(shí)才考慮使用這些矢量圖形。

    其它策略

    有時(shí)候我們可能對(duì)一張圖片進(jìn)行重復(fù)利用,比如一張圖片僅僅是整體顏色的變換可以使用setColorFilter或者tint。盡量減少使用幀動(dòng)畫,那可是一堆圖片呀。

    壓縮資源

    要啟用資源壓縮,請(qǐng)?jiān)?build.gradle 文件中將 shrinkResources 屬性設(shè)置為 true。

    android {...buildTypes {release {shrinkResources trueminifyEnabled trueproguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'}} }

    ?

    資源壓縮器目前不會(huì)移除 values/ 文件夾中定義的資源(例如字符串、尺寸、樣式和顏色)。這是因?yàn)?Android 資源打包工具 (AAPT) 不允許 Gradle 插件為資源指定預(yù)定義版本。

    同時(shí),我們也可以指定哪些資源可以保留下來。

    例如,將下邊的代碼保存在 res/raw/keep.xml。構(gòu)建不會(huì)將該文件打包到 APK 之中。

    <?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools"tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"tools:discard="@layout/unused2" />

    ?

    resources有以下屬性:

    tools:keep 指出哪些資源會(huì)保留 tools:discard 指定哪些資源需要剔除 tools:shrinkMode 資源壓縮模式,有兩種取值strict和safe,默認(rèn)為safe

    safe和strict的優(yōu)化策略:

    safe可以簡(jiǎn)單理解為安全模式,它會(huì)盡最大努力檢查代碼中可能會(huì)使用到的資源進(jìn)行保留,避免運(yùn)行時(shí)錯(cuò)誤。

    如果你的代碼調(diào)用 Resources.getIdentifier(),這就表示你的代碼將根據(jù)動(dòng)態(tài)生成的字符串查詢資源名稱。當(dāng)你執(zhí)行這一調(diào)用時(shí),默認(rèn)情況下資源壓縮器會(huì)采取防御性行為,將所有具有匹配名稱格式的資源標(biāo)記為可能已使用,無法移除。

    String name = String.format("img_%1d", angle + 1); res = getResources().getIdentifier(name, "drawable", getPackageName());

    ?

    img_ 前綴的資源標(biāo)記為已使用。

    在strict模式下,img_前綴的資源會(huì)做未使用的處理,因此你需要使用tools:keep手動(dòng)進(jìn)行已使用標(biāo)識(shí)。

    移除未使用的備用資源

    我們知道google給我們的apk提供了國(guó)際化支持,如適應(yīng)不同的屏幕分辨率的drawable資源,還有適應(yīng)不同語言的字符串資源等等,但是在很多情況下我們只需要一些指定分辨率和語言的資源就可以了,這個(gè)時(shí)候我們可以使用resConfigs方法來配置。

    defaultConfig {// 對(duì)于國(guó)際化支持只打包中文資源,resConfigs "zh-rCN" }

    ?

    04 lib中資源優(yōu)化

    這里我們主要講一下lib中動(dòng)態(tài)鏈接庫(kù)的優(yōu)化策略,也就是SO文件。如果你有NDK的開發(fā)經(jīng)驗(yàn)可能會(huì)更容易理解一些。

    為了支持不同指令集的情況,應(yīng)用可能會(huì)包含armeabi、armeabi-v7a、x86的SO文件等。

    目前主流的機(jī)型都是支持armeabi-v7a的,并且armeabi-v7a兼容armeabi。所以在一般的開發(fā)中我們只需要使用armeabi-v7a 進(jìn)行ABI支持。

    有些SO庫(kù)可以采用網(wǎng)絡(luò)下載,把負(fù)擔(dān)放到用戶安裝完應(yīng)用之后。對(duì)于哪些SO文件可以放到網(wǎng)絡(luò)中加載,還需要看具體業(yè)務(wù)情況。

    題外話,如果運(yùn)行時(shí)找不到SO的話,會(huì)導(dǎo)致應(yīng)用崩潰。

    java.lang.UnsatisfiedLinkError: Couldn't load stlport_shared from loader dalvik.system.PathClassLoader: findLibrary returned null at java.lang.Runtime.loadLibrary(Runtime.java:365) at java.lang.System.loadLibrary(System.java:535) at com.your.app.NativeClass.<clinit>(Native.java:16) ... 63 moreCaused by: java.lang.UnsatisfiedLinkError: Library stlport_shared not found at java.lang.Runtime.loadLibrary(Runtime.java:461) at java.lang.System.loadLibrary(System.java:557) at com.your.app.NativeClass.<clinit>(Native.java:16) ... 5 more

    ?

    我們也是有辦法應(yīng)對(duì)的,可以參見這個(gè)開源項(xiàng)目ReLinker

    另外關(guān)于SO的優(yōu)化我會(huì)單獨(dú)拿出來講一講。



    原文鏈接:https://www.jianshu.com/p/5921e9561f5f

    總結(jié)

    以上是生活随笔為你收集整理的你必须要懂的APK瘦身知识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。