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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android包体积优化(常规、进阶、极致)

發布時間:2023/12/14 Android 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android包体积优化(常规、进阶、极致) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

包大小的重要性已經不需要多說,包大小直接影響用戶的下載,留存,甚至部分廠商預裝強制要求必須小于一定的值。但是隨著業務的迭代開發,應用會越來越大,安裝包會不停的膨脹,因此包大小縮減是一個長期持續的治理過程。

  • 提升下載轉化率,安裝包越小,轉化率越高。
  • 降低渠道推廣成本。
  • 降低安裝時間,文件拷貝、Library解壓、編譯ODEX、簽名校驗這些,包體積越大越耗時。
  • 降低運行時內存等等。

環境

  • Android Studio Arctic Fox | 2020.3.1 Patch 2
  • AGP 7.0
  • 項目地址:wanandroid_jetpack

優化前

  • 4.7MB,4.2MB是google play下載的大小,會有壓縮。

除了AS自帶的Analyzer之外,還有ApkChecker、ClassyShark等工具。

APK的組成

文件描述
libso文件,不同的cpu架構
res編譯后的資源文件,drawable、layout等
assets應用程序的資源、字體、音頻文件等
classes(n).dexdx編譯后的java文件
META-INF簽名信息相關
resources.arsc二進制資源文件
kotlin編譯后的kotlin文件
AndroidManifest.xml清單文件

APK構建流程


這是官方新版的打包流程,雖然省略了一些步驟,但是大致的流程還是比較清晰的。
再次簡化一下:

資源文件、Java文件 > dex文件 > APK

優化思路

APK本質是一個壓縮文件,是打包后的產物,那可以作為切入點的階段就是打包前、以及打包中。

  • 打包前,即減少打包的文件,比如無用的資源、代碼;
  • 打包中,對打包中的產物進行壓縮,比如資源文件、So文件;

關鍵詞:減少、壓縮。

常規操作

1.Lint檢測無用資源文件

Analyze > Run Inspection by Name > Unused resources



檢測結果:

確定無用刪除即可。

注意:
因為lint是本地靜態掃描,所以動態引用的資源文件并不會識別出來,也會出現在檢測列表里。

2.Lint檢測代碼

Analyze > Inspect code


檢測結果:

因為這個項目是用kotlin寫的,所以直接看kotlin目錄下的檢測結果。

注意:
因為lint是本地靜態掃描,所以反射、動態引用的class并不會識別出來,也會出現在檢測列表里。

3.圖片壓縮

推薦使用tinypng在線壓縮。

4.TinyPngPlugin

手動壓縮畢竟不高效,可以使用TinyPngPlugin一鍵壓縮。
plugins搜索TinyPng安裝即可。(新版AS安裝完plugin已經不需要重啟了)

壓縮結果:

9張圖片,可以看到效果還是非常可觀的。
如果圖片多,效果更加明顯。

經過上面的操作,包體積減小4%,這還只是一個4.7MB的APK而已。

5.WebP

那這9張圖還能繼續優化嗎?
可以,WebP格式的體積更小,而已AS也提供了一鍵轉換支持。

以ic_avatar.png為例:

ic_avatar.png優化后
原始大小113.09KB
TingPng壓縮36.85KB
WebP8.66KB

可以看到,轉WebP之后,較原始大小減少了近93%,恐怖如斯~

6.開啟混淆

minifyEnabled true,默認啟用R8代碼縮減功能。

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

慎用R8,因為:

R8 會忽略試圖修改默認優化行為的所有 ProGuard 規則,例如 -optimizations 和 - optimizationpasses。

可以開啟混淆,而不使用R8。

android.enableR8=false android.enableR8.libraries=false

混淆參考:Android混淆從入門到精通

7.縮減資源

shrinkResources true

假如有一些資源文件不確定還用不用,也不敢刪,或者不確定需求是否會變更,所以先留著,那這種情況怎么辦呢?
可以使用shrinkResources來縮減資源。

buildTypes {debug {minifyEnabled false}release {shrinkResources trueminifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}

要配合混淆minifyEnabled一起使用才行,原理也很簡單,代碼移除之后,引用的資源也就變成無用資源了,才可以進一步縮減。

8.so文件縮減

比如集成了一個三方的直播或者瀏覽器,可能會提供很多so文件,起初可能是一股腦的copy進項目,但并不一定都用的到。
比如各種cpu架構的so:

app/build/intermediates/cmake/universal/release/obj/ ├── armeabi-v7a/ │ ├── libgameengine.so │ ├── libothercode.so │ └── libvideocodec.so ├── arm64-v8a/ │ ├── libgameengine.so │ ├── libothercode.so │ └── libvideocodec.so ├── x86/ │ ├── libgameengine.so │ ├── libothercode.so │ └── libvideocodec.so └── x86_64/├── libgameengine.so├── libothercode.so└── libvideocodec.so

目前市面上的手機cpu都是arm架構的,所以保留arm的一種即可(定制的除外),armeabi-v7a或armeabi都可,其他直接刪除。

android {defaultConfig {ndk {abiFilters 'armeabi-v7a'}} }

如果開發需要模擬器調試,就加上x86的架構,正式包記得去掉,或者在local.properties中用變量控制一下。

這塊如果之前沒有優化過,而又有很多so文件的話,或許可以減少30%以上,恐怖如斯!

9.移除未使用的備用資源


很多出海的應用會做國際化,但也適配不了這么多的語言。
除了自己app的之外,還有一些官方的、三方的,可以統一配置支持的語言。

defaultConfig {resConfigs("en","zh","zh-rCN")}

資源文件同理

defaultConfig {resConfigs("xxhdpi","xxxhdpi")}

10.小結

針對上面的操作做個小結,看看目前效果如何。

2MB,包體積減少57%,恐怖如斯!

如果是大型項目,收益非常可觀。

author:yechaoa

進階操作

上面只是一些常規操作,下面看一些進階操作。

1.resources.arsc資源混淆

資源混淆就是將原本冗長的資源路徑變短,例如將res/drawable/wechat變為r/d/a。
開源工具AndResGuard。

2.移除無用的三方庫

引入之后未使用的,或者是功能下架之后未移除的。

3.功能重復的三方庫整合

比如glide和picasso,都是圖片庫,保留其一即可。

4.ReDex

dex文件是打包中的產物,redex是facebook開源的分包優化方案。
可以參考:ReDex。

5.so動態加載

前面已經做了so文件縮減,但是可能so文件占比還是比較大,可以考慮除了首次啟動外的so文件做動態下發。
也就是插件化的思想,按需加載,但是收益很大的同時,風險也很大,有很多case需要考慮到,比如下載時機、網絡環境、線程進程,加載失敗是否有降級策略等等。

可以參考facebook開源的SoLoader。

6.插件化

按需加載,收益越大風險越大,風險同上。

極致操作

那如果我想做到極致,還有哪些騷操作呢,ok,繼續。

1.原生改用H5或小程序等方案

有些功能可能原生做就顯得太重,比如各種促銷活動,需要加載各種大圖,原生既重又不夠動態化,這個時候H5是一種很好的替代方案。
但是如果你原本就不支持H5或者小程序的話,接入這種能力可能反而會加大包體積,做好對比。

2.砍功能

有些功能可能想的很美好,但上線之后收益并不大,是否需要重新思考價值點,最好找到數據依托,再跟產品打架。

3.修改三方庫的源碼,不需要的代碼剔除

比如引入了一個功能很齊全的三方庫utils,但實際只用到幾個,對源碼進行抽取也能減少包體積,同時還能減少網絡下載的編譯時間。
弊端就是升級成本較大。

4.圖片網絡化

即把圖片上傳到服務器,通過動態下載的方式減少包體積,弊端就是首次加載的時候依賴網絡環境,對加載速度、流量需要做一個平衡。
圖片可以預加載,但是流量消耗是無法避免了,如果比較在意流量指標,需要權衡了。

5.DebugItem

DebugItem 里面主要包含兩種信息:

  • 調試的信息。函數的參數變量和所有的局部變量。
  • 排查問題的信息。所有的指令集行號和源文件行號的對應關系。

去除debug信息與行號信息,如果不是極致,不推薦。
可以參考支付寶的這篇 支付寶 App 構建優化解析:Android 包大小極致壓縮。

6.R Field內聯

內聯R Field可以解決R Field過多導致MultiDex 65536的問題,而這一步驟對代碼瘦身能夠起到明顯的效果。

美團代碼片段:

ctBehaviors.each { CtBehavior ctBehavior ->if (!ctBehavior.isEmpty()) {try {ctBehavior.instrument(new ExprEditor() {@Overridepublic void edit(FieldAccess f) {try {def fieldClassName = JavassistUtils.getClassNameFromCtClass(f.getCtClass())if (shouldInlineRField(className, fieldClassName) && f.isReader()) {def temp = fieldClassName.substring(fieldClassName.indexOf(ANDROID_RESOURCE_R_FLAG) + ANDROID_RESOURCE_R_FLAG.length())def fieldName = f.fieldNamedef key = "${temp}.${fieldName}"if (resourceSymbols.containsKey(key)) {Object obj = resourceSymbols.get(key)try {if (obj instanceof Integer) {int value = ((Integer) obj).intValue()f.replace("\$_=${value};")} else if (obj instanceof Integer[]) {def obj2 = ((Integer[]) obj)StringBuilder stringBuilder = new StringBuilder()for (int index = 0; index < obj2.length; ++index) {stringBuilder.append(obj2[index].intValue())if (index != obj2.length - 1) {stringBuilder.append(",")}}f.replace("\$_ = new int[]{${stringBuilder.toString()}};")} else {throw new GradleException("Unknown ResourceSymbols Type!")}} catch (NotFoundException e) {throw new GradleException(e.message)} catch (CannotCompileException e) {throw new GradleException(e.message)}} else {throw new GradleException("******** InlineRFieldTask unprocessed ${className}, ${fieldClassName}, ${f.fieldName}, ${key}")}}} catch (NotFoundException e) {}}})} catch (CannotCompileException e) {}} }

同時可以參考字節開源的shrink-r-plugin,還有滴滴開源的booster。

7.圖片著色器

針對同圖不同色的處理,可以使用tint,比如原本是一個黑色的返回icon,現在另一個頁面要用白色了,就不需要兩張圖了,而是使用tint來修改為白色即可。

<ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/ic_back_black"android:tint="@android:color/white" />

8.減少ENUM的使用

每減少一個ENUM可以減少大約1.0到1.4 KB的大小。

包體積監控

包體積監控應該作為發布流程的一個環節,最好是做到平臺化、流程化,否則很難持續,沒幾個版本包體積又漲上來了。

大致思想:當前版本與上一個版本的包大小做對比,超過200KB需要審批。臨時審批需要給出后續優化方案等等。

參考文檔

  • Improve your code with lint checks
  • Shrink, obfuscate, and optimize your app
  • Android App包瘦身優化實踐
  • ReDex
  • SoLoader
  • 支付寶 App 構建優化解析:Android 包大小極致壓縮
  • AndResGuard
  • 深入探索 Android 包體積優化
  • Android開發高手課包體積優化

總結

以上是生活随笔為你收集整理的Android包体积优化(常规、进阶、极致)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。