Android性能優(yōu)化之APK瘦身詳解(瘦身73%)

公司項(xiàng)目在不斷的改版迭代中,代碼在不斷的累加,終于apk包不負(fù)重負(fù)了,已經(jīng)到了八十多M了。可能要換種方式表達(dá),到目前為止沒(méi)有正真的往外推過(guò),一直在內(nèi)部執(zhí)行7天討論需求,5天代碼實(shí)現(xiàn)的階段。你在寫上個(gè)版本的內(nèi)容,好了,下個(gè)版本的更新內(nèi)容已經(jīng)定稿了?;谶@種快速開(kāi)發(fā)的現(xiàn)狀,我們app優(yōu)化前已經(jīng)有87.1M了,包大了,運(yùn)營(yíng)說(shuō)這樣轉(zhuǎn)化不高,只能好好搞一下咯。優(yōu)化過(guò)后包大小為23.1M(優(yōu)化了73%,不要說(shuō)我標(biāo)題黨)。好了好了,我要闡述我的apk超級(jí)無(wú)敵魔鬼瘦身之心得了。

文章主要內(nèi)容從理論出發(fā),再做實(shí)際操作。分為下面幾個(gè)方面:1. 結(jié)構(gòu)分析, 2.具體實(shí)操 3. 總結(jié) 4. 參考資料

1. 結(jié)構(gòu)分析

首先上傳一張瘦身前通過(guò)Analyze app分析出來(lái)的圖片(打開(kāi)方式:Android Studio下 ——> Build——> Analyze app):

APK包結(jié)構(gòu)如下:

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

通過(guò)分析圖可以知道,目前app主要是so文件占比比較大,占了31.7M,占了整個(gè)應(yīng)用是38.2%。其次是assets目錄,整個(gè)目錄占了32M,第三就是資源文件res目錄了。所以接下來(lái)我們處理步驟就是按這個(gè)順序來(lái)處理。(簡(jiǎn)單說(shuō)下圖中的Raw File Size(磁盤解壓后的大?。┖虳ownLoad Size(從應(yīng)用商店下載的大?。?,如果想了解更多關(guān)于Analyaer分析的知識(shí),可以參考這篇文章使用APK Analyzer分析你的APK),分析了包結(jié)構(gòu)組成之后,我們可以開(kāi)始瘦身操作了。

2.具體實(shí)操

1. 對(duì)lib目錄下的文件進(jìn)行瘦身處理

1. 修改lib配置:

參考資料
so文件的優(yōu)化:通常我們?cè)谑褂肗DK開(kāi)發(fā)的時(shí)候,我們經(jīng)常會(huì)有如下這么一段代碼:

ndk {
            //設(shè)置支持的so庫(kù)架構(gòu)
            abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64", "armeabi"
        }

最后我的修改代碼如下:

ndk     {
            //設(shè)置支持的so庫(kù)架構(gòu)
            abiFilters "armeabi-v7a"
        }

接下來(lái)說(shuō)明這么做的依據(jù):
看上面圖分析,armeabi-v7主要不支持ARMv5(1998年誕生)和ARMv6(2001年誕生).目前這兩款處理器的手機(jī)設(shè)備基本不在我公司的適配范圍(市場(chǎng)占比太少)。
而許多基于 x86 的設(shè)備也可運(yùn)行 armeabi-v7a 和 armeabi NDK 二進(jìn)制文件。對(duì)于這些設(shè)備,主要 ABI 將是 x86,輔助 ABI 是 armeabi-v7a。
最后總結(jié)一點(diǎn):如果適配版本高于4.1版本,可以直接像我上面這樣寫,當(dāng)然,如果armeabi-v7a不是設(shè)備主要ABI,那么會(huì)在性能上造成一定的影響。
參考文章:安卓app打包的時(shí)候還需要兼容armeabi么?

好了,我們?cè)俅蛞淮伟囋嚒?/p>


確實(shí)有點(diǎn)震驚,一下子包小了這么多,從87.1M到51.9M,容我好好算算少了多少M(fèi).趕快讓測(cè)試幫忙測(cè)一下。基于之前的理論知識(shí),心里還是有點(diǎn)底。果然,測(cè)試效果和之前是一樣的。心里的石頭先落下羅。

2. 重新編譯so文件,用更小的庫(kù)代替

相信很多開(kāi)發(fā)者都有這種苦惱,很多第三方我們導(dǎo)入進(jìn)來(lái)只用到其中很小一部分功能,大部分功能都是我們用不上的。這時(shí)候我們找到源代碼,將我們需要的那部分代碼提取出來(lái),重新編譯成新的so文件,再導(dǎo)入到我們項(xiàng)目中。當(dāng)然,如果之前沒(méi)有編譯過(guò)so文件,這部分建議做最后的優(yōu)化去處理。不然你會(huì)遇到很多問(wèn)題。上一波處理后的效果圖:


這里說(shuō)下,因?yàn)轫?xiàng)目中有使用到ffmpeg庫(kù),之前導(dǎo)入的第三方的放在assets文件夾下,重寫編寫后的so庫(kù)文件放在lib文件夾下,所以lib文件夾反而大了。從51.9M到35.6M,效果還是蠻不錯(cuò)的。

對(duì)了,別問(wèn)我為什么assets文件夾下為什么還有12.6M資源,因?yàn)楹芏?mp3都是第三方的人臉識(shí)別必備配置文件,我也很無(wú)奈。

2. 優(yōu)化res,assets文件大小

1. 手動(dòng)lint檢查,手動(dòng)刪除無(wú)用資源

在Android Studio中打開(kāi)“Analyze” 然后選擇"Inspect Code...",范圍選擇整個(gè)項(xiàng)目,然后點(diǎn)擊"OK"。配置如下:

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

打開(kāi)網(wǎng)址,將大圖片導(dǎo)入到tinypng,替換之前的圖片資源。

3. 大部分圖片使用Webp格式代替。

可以給UI提要求,讓他們將圖片資源設(shè)置為Webp格式,這樣的話圖片資源會(huì)小很多。如果想了解更多關(guān)于webp,請(qǐng)點(diǎn)擊這里webp,當(dāng)然,如果對(duì)圖片顏色通道要求不高,可以考慮轉(zhuǎn)jpg,最好用webp,因?yàn)樾Ч选?/p>

4. 盡量不要在項(xiàng)目中使用幀動(dòng)畫

一個(gè)幀動(dòng)畫幾十張圖片,再怎么壓縮都還是占很大內(nèi)存比重的。所以建議是讓UI去搞,這里可以參考使用lottie-android,如果項(xiàng)目中動(dòng)畫效果多的話效果更加明顯。當(dāng)然這就要辛苦我們UI設(shè)計(jì)師大大了。

5. 使用gradle開(kāi)啟shrinkResources

移除無(wú)用資源文件,下面是我的配置:

 buildTypes {
        release {
            // 不顯示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //混淆
            minifyEnabled true
            // 移除無(wú)用的resource文件
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }

通過(guò)上述步驟操作,apk效果如下:

又優(yōu)化了將近5M,別問(wèn)我為什么還有7.5M,里面大量的gif和webp格式的動(dòng)圖,都是UI丟給我的,一個(gè)2.7M.后面再慢慢和他細(xì)究這個(gè)問(wèn)題。后面要做的兩部分,一部分是將資源文件下的所有g(shù)if圖放后臺(tái)下載處理,第二個(gè)是和UI討論下如何減小webp 動(dòng)圖的大?。ㄎ铱雌渌脚_(tái)只有100K的樣子,給我的就2.7M?)。

3. 減少chasses.dex大小

classes.dex中包含了所有的java代碼,當(dāng)你打包時(shí),gradle會(huì)將所有模板力的.class文件轉(zhuǎn)換成classes.dex文件,當(dāng)然,如果方法數(shù)超過(guò)64K,將要新增其他文件進(jìn)行存儲(chǔ)。可以通過(guò)multidexing分多個(gè)文件,比如我這里的chasses2.dex。換句話說(shuō),就是減少代碼量。我們可以通過(guò)以下方法來(lái)實(shí)現(xiàn):

  1. 盡量減少第三方庫(kù)的引用,這個(gè)在上面我們已經(jīng)做過(guò)優(yōu)化了。
  2. 避免使用枚舉,這里特別去網(wǎng)上查了一下,具體可以參考下這篇文章Android 中的 Enum 到底占多少內(nèi)存?該如何用?,得出的結(jié)論是,可能幾十個(gè)枚舉的內(nèi)存占有量才相當(dāng)一張圖片這樣子,優(yōu)化效果也不會(huì)特別明顯。當(dāng)然,如果你是個(gè)追求極致的人,我不反對(duì)你用靜態(tài)常量替代枚舉。
  3. 如果你的dex文件太大,檢查是否引入了重復(fù)功能的第三方庫(kù)(圖片加載庫(kù),glide,picasso,fresco,image_loader,如果不是你一個(gè)人單獨(dú)開(kāi)發(fā)完成的很容易出現(xiàn)這種情況),盡量做到一個(gè)功能點(diǎn)一個(gè)庫(kù)解決。

關(guān)于classes.dex文件大小分析可以參考這篇譯文使用 APK Analyzer 分析你的 APK

4. 其他

  1. 用7zip代替壓縮資源。
  2. 刪除翻譯資源,只保留中英文
  3. 嘗試將andorid support庫(kù)徹底踢出你的項(xiàng)目。
  4. 嘗試使用動(dòng)態(tài)加載so庫(kù)文件,插件化開(kāi)發(fā)。
  5. 將大資源文件放到服務(wù)端,啟動(dòng)后自動(dòng)下載使用。

3. 總結(jié)

好了,說(shuō)道這里基本上就結(jié)束了,apk包從87.1M減小到了23.1M(優(yōu)化了73%,不要說(shuō)我標(biāo)題黨)已經(jīng)差不多了,關(guān)于第四部其他部分的優(yōu)化我是沒(méi)有進(jìn)行再操作的。因?yàn)楣具\(yùn)營(yíng)覺(jué)得二三十M的包比較真實(shí),太小了就太假了。所以我暫時(shí)就不進(jìn)行優(yōu)化了。如果再上面提到的部分通過(guò)所有將所有非啟動(dòng)頁(yè)面首頁(yè)之外的所有資源,so庫(kù)放服務(wù)端,理論上apk包大小能在10M以內(nèi)這樣子。當(dāng)然我們有做到就不多加評(píng)價(jià)了。最后,如果對(duì)插件化開(kāi)發(fā)感興趣的話可以參考下這篇文章Android全面插件化方案-RePlugin踩坑。最后,如果你在Android上有什么疑問(wèn),可以添加我的同名微信公眾號(hào)aserbao和我一塊交流。

個(gè)人微信 公眾號(hào) 微信交流群過(guò)期請(qǐng)點(diǎn)擊這里

文章本來(lái)是周三的差不多的,到今天才發(fā),還是有點(diǎn)小偷懶了。最后祝大家五一快樂(lè),出門玩的開(kāi)心。如果你看到了這里,覺(jué)得文章寫得不錯(cuò)就給個(gè)贊唄?如果你覺(jué)得那里值得改進(jìn)的,請(qǐng)給我留言。一定會(huì)認(rèn)真查詢,修正不足。謝謝。


這里寫圖片描述

4. 參考資料:

文章主要參考文章如下,文章有少部分文字參考了下面文章中的語(yǔ)句。如果有侵犯到作者權(quán)益,請(qǐng)和我聯(lián)系,查實(shí)后馬上刪除。

  1. Android APK 瘦身 - JOOX Music項(xiàng)目實(shí)戰(zhàn)
  2. APK 瘦身記,如何實(shí)現(xiàn)高達(dá) 53% 的壓縮效果
  3. 使用APK Analyzer分析你的APK
  4. 安卓app打包的時(shí)候還需要兼容armeabi么?
  5. 百度百科webp
  6. Android 中的 Enum 到底占多少內(nèi)存?該如何用?

推薦閱讀:Android性能優(yōu)化之內(nèi)存泄漏無(wú)處可藏(圖文)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,939評(píng)論 25 709
  • 1、 前言 如果你對(duì)App優(yōu)化比較敏感,那么Apk安裝包的大小就一定不會(huì)忽視。關(guān)于瘦身的原因,大概有以下幾個(gè)方面:...
    未來(lái)的理想閱讀 11,849評(píng)論 4 40
  • 本文來(lái)自尚妝Android團(tuán)隊(duì)青峰發(fā)表于尚妝博客 APK瘦身探索 最近幾周一直在研究如何為APK瘦身,折騰了很久,...
    尚妝產(chǎn)品技術(shù)刊讀閱讀 1,888評(píng)論 1 23
  • 2014年11月14日。 我們忘記時(shí)光,又回顧時(shí)光。 那天下午我,守德,還有荔枝,坐上的那輛離開(kāi)校園的車。 我記得...
    辰七閱讀 696評(píng)論 0 2
  • 哈哈哈哈,我們家爸爸的幾兄弟寫字都不錯(cuò),尤其是我大白,滿爹就稍微次一些(?>ω<*?),但是,似乎好像都沒(méi)遺傳下來(lái)...
    跳梁貴妃閱讀 241評(píng)論 0 2

友情鏈接更多精彩內(nèi)容