APK瘦身探索

最近幾周一直在研究如何為APK瘦身烛卧,折騰了很久,是時(shí)候?qū)懫┛涂偨Y(jié)一下了妓局,雖然已經(jīng)準(zhǔn)備了下周一要在客戶端周會(huì)分享用的PPT:APK瘦身探索总放。

價(jià)值

雖然說(shuō)APK瘦身對(duì)于Android對(duì)應(yīng)用可分配內(nèi)存的限制影響不大,但是還是有一些影響的好爬,就以圖片為例局雄,將一些小圖標(biāo)替換為iconfont能有效減小內(nèi)存的分配,防止OOM的出現(xiàn)存炮。

另外炬搭,無(wú)論是iOS開發(fā)者還是Android開發(fā)者都應(yīng)該嘗試最好學(xué)會(huì)如何為IPA或APK瘦身,不僅僅是為了幫助用戶省流量穆桂、減少下載時(shí)間宫盔、減少占用的存儲(chǔ)空間等等,更重要的是為了提高轉(zhuǎn)化率(注意:本文的轉(zhuǎn)化率均指下載轉(zhuǎn)化率)享完。

那轉(zhuǎn)化率是什么呢灼芭?

舉個(gè)栗子:你的應(yīng)用大小是 18MB ,有100個(gè)潛在用戶想要去下載嘗試使用般又,結(jié)果有20個(gè)用戶嫌棄安裝包太大直接揚(yáng)長(zhǎng)而去彼绷,有20個(gè)用戶在等待下載的過(guò)程中取消下載,最終只有60個(gè)用戶真正下載安裝茴迁,那么應(yīng)用的轉(zhuǎn)化率就是 60/100 = 60% 寄悯。

那為什么要提高轉(zhuǎn)化率呢?

因?yàn)橛脩粼诩m結(jié)下載你的產(chǎn)品還是你的競(jìng)品的時(shí)候堕义,往往會(huì)選擇那個(gè)體驗(yàn)最好猜旬、功能最多、性能最好倦卖、包最小的洒擦。

工具

如何有條理的為APK瘦身,必須知道APK的目錄結(jié)構(gòu)糖耸,不過(guò)在講述這個(gè)之前,我這里先介紹幾個(gè)工具丘薛,在后文會(huì)用到嘉竟。

AndroidStudio2.2.3

AndroidStudio升級(jí)到版本2.2.3之后提供了Analyze APK的功能(不過(guò)作為AS粉想必已經(jīng)升到AS2.3了吧,哈哈),我們可以借助該工具清楚的了解APK的下載大小舍扰、解壓之后的大小倦蚪、內(nèi)部各個(gè)文件夾或文件占用的大小等信息,進(jìn)而得知那些地方可以優(yōu)化边苹。下圖為目前我司測(cè)試版APK的內(nèi)部信息:

APK Info.png

另外使用該工具還可以反編譯資源文件陵且、還原layout中的資源id,分析DEX个束、顯示每一個(gè)文件夾或文件的方法數(shù)慕购,分析哪些第三方庫(kù)方法數(shù)很多但實(shí)際只用到了一部分等其他功能。

最后如何使用該工具茬底?有以下兩種方式:

  1. 直接將APK拖拽進(jìn)入AndroidStudio即可
  2. 點(diǎn)擊菜單欄Build-Analyze APK...選項(xiàng)沪悲,再選擇需要分析的APK即可

NimbleDroid

NimbleDroid 是美國(guó)哥倫比亞大學(xué)的博士創(chuàng)業(yè)團(tuán)隊(duì)研發(fā)出來(lái)的自動(dòng)化分析Android app性能指標(biāo)的系統(tǒng),分析的方式有靜態(tài)和動(dòng)態(tài)兩種方式:

其中靜態(tài)分析可以分析出APK安裝包中大文件排行榜阱表,各種知名SDK的大小以及占代碼整體的比例殿如,各種類型文件的大小以及占排行,各種知名SDK的方法數(shù)以及占所有dex中方法數(shù)的比例,針對(duì)緩慢的方法最爬,緩慢的第三方SDK和內(nèi)存泄漏涉馁。

其中動(dòng)態(tài)分析可以測(cè)量生成的速度、網(wǎng)絡(luò)爱致、內(nèi)存和磁盤使用率烤送。

我用了一下上面這個(gè)工具,感覺還是不錯(cuò)的蒜鸡,下面我們來(lái)看幾張有逼格的圖(圖中數(shù)據(jù)來(lái)自于我司測(cè)試版APK):

APK內(nèi)部各類型對(duì)應(yīng)文件占用的大小

Size by Type.png

APK內(nèi)部各個(gè)類庫(kù)的方法數(shù)

Method Count.png

APK啟動(dòng)過(guò)程中各個(gè)方法的執(zhí)行時(shí)間

Hung CPU Methods.png

ClassShark

ClassShark 是一款查看Android執(zhí)行文件(apk)的瀏覽工具胯努,目前有兩個(gè)android App(Apk)和桌面(jar)的版本。

使用這款工具逢防,可以很方便的打開APK叶沛、Class、Jar忘朝、res等文件和分析里面的內(nèi)容灰署。

ClassShark.png

不過(guò)目前這個(gè)工具并不需要我們單獨(dú)使用,因?yàn)锳S內(nèi)部的分析工具就是用的這個(gè)局嘁。

通過(guò)以上工具溉箕,我們可以方便快速的分析APK,找出那些可以優(yōu)化的部分悦昵,為了更加有條理的進(jìn)行講解肴茄,下面我會(huì)按照APK的目錄結(jié)構(gòu)來(lái)逐條闡述。

APK目錄結(jié)構(gòu)

APK目錄結(jié)構(gòu).png

上述表格左邊部分是APK內(nèi)部默認(rèn)存在的文件夾或文件但指,表格右邊對(duì)于各個(gè)文件夾或文件進(jìn)行了簡(jiǎn)要的概述寡痰,詳細(xì)的說(shuō)明會(huì)在之后根據(jù)左邊的順序一一講解抗楔。

assets目錄

assets目錄用于存放需要打包到應(yīng)用程序的靜態(tài)文件,它包含以下幾個(gè)特性:

  1. 使用AssetManager類管理資源

  2. assets目錄內(nèi)部文件不會(huì)被系統(tǒng)編譯

  3. assets目錄支持任意深度的子目錄

  4. 獲取資源需要使用/assets開始(不包含它)的相對(duì)路徑名拦坠,具體代碼如下所示:

    String fileNames[] = context.getAssets().list(path);
    

那么连躏,assets目錄下都可以放什么文件呢?

說(shuō)實(shí)在的贞滨,assets目錄可以存放各種文件入热,不過(guò)正常情況下,一般只存放以下幾種文件:字體文件晓铆、WEB頁(yè)面勺良、配置文件、某些圖片尤蒿。

上述幾種文件除了配置文件之外郑气,我們都可以進(jìn)行適當(dāng)?shù)膲嚎s處理:

字體文件:可以使用字體資源文件編輯神器Glyphs進(jìn)行壓縮,其壓縮方式其實(shí)就是通過(guò)刪除不需要的字符從而減少APK的大小腰池。

WEB頁(yè)面:可以考慮使用7zip壓縮工具對(duì)該文件進(jìn)行壓縮尾组,在正式使用的時(shí)候解壓

某些圖片:可以使用tinypng進(jìn)行圖片壓縮, 目前tinypng已經(jīng)支持png和jpg圖片示弓、.9圖的壓縮

lib目錄

lib目錄用于存放通過(guò)C或C++編寫編譯生成的so文件(native庫(kù)/JNI開發(fā))讳侨,其基本目錄結(jié)構(gòu)如下圖所示:

lib目錄結(jié)構(gòu).png

因?yàn)槟壳笆袌?chǎng)上主流的架構(gòu)還只是arm架構(gòu),所以如果不是必要的話奏属,可以考慮不支持x86和mips架構(gòu)跨跨,但這并不意味著CPU是x86或mips架構(gòu)的手機(jī)就不能正常安裝使用APK了,因?yàn)榉旁赼rm目錄下的so庫(kù)是可以兼容到其他架構(gòu)的囱皿;

另外arm架構(gòu)中的eabi-v7a相比于eabi只是在圖形渲染方面有了很大的改進(jìn)勇婴,所以如果so庫(kù)對(duì)圖形渲染沒(méi)有很高的要求的話,完全可以把so庫(kù)只存放在arm eabi目錄中嘱腥,這樣可以大大減小APK的體積耕渴。

上面的說(shuō)明可能比較籠統(tǒng),下面就拿淘寶齿兔、微信的APK來(lái)說(shuō)明一下:

APK_taobao.png
APK_weixin.png

可以看出淘寶和微信也是這樣處理橱脸,所以我們其實(shí)也可以這樣操作。

res目錄

res目錄用于存放應(yīng)用程序的資源文件分苇,主要包括布局文件添诉、圖片、XML配置文件等医寿,它包含以下幾個(gè)特性:

  1. 使用Resources類管理資源
  2. res目錄內(nèi)部文件會(huì)被系統(tǒng)編譯
  3. res目錄不支持任意深度的子目錄
  4. 獲取資源不需要通過(guò)相對(duì)路徑找尋栏赴,因?yàn)槲募?huì)被系統(tǒng)編譯,所以需要通過(guò)資源ID(注:資源ID被存放在resources.arsc文件中)查找

其基本目錄結(jié)構(gòu)如下圖所示:

res目錄結(jié)構(gòu).png

上圖比較全面的列舉了res目錄下經(jīng)常包含的子目錄和文件靖秩,并解釋了各個(gè)子目錄或文件的含義须眷。

根據(jù)上圖我們顯然可以發(fā)現(xiàn)乌叶,res目錄就是我們APK瘦身里面的一大重要部分了,由于其包含的知識(shí)很大柒爸,下面我會(huì)分章節(jié)進(jìn)行闡述,盡量一一闡述清楚事扭。

只用一套圖

首先我給出這么一個(gè)結(jié)論:一個(gè)APK盡量只用一套圖片捎稚,從內(nèi)存占用和適配的角度考慮,建議放在xhdpi文件夾下求橄。

那么為什么要把圖片放在xhdpi文件夾下面呢今野?

由于此處知識(shí)涉及到Android屏幕適配方面的知識(shí),比較復(fù)雜罐农。本文是關(guān)于APK瘦身的条霜,所以就不詳細(xì)講解了。下面進(jìn)行必要的闡述涵亏,首先讓我們來(lái)看兩張圖:

201612&201701設(shè)備分辨率_Android.png
201612&201701設(shè)備分辨率_iOS.png

從上面兩張圖我們可以得到以下兩點(diǎn)信息:

  1. Android主要的設(shè)備分辨率為:1280*720宰睡、1920*1080
  2. iOS主要的設(shè)備分辨率為:1334*750、2208*1242气筋、1136*640

可能有人要問(wèn)了拆内,得到這兩點(diǎn)信息有什么用?

恩宠默,單單這樣看并不能知道什么麸恍,為了幫助大家了解,我繪制了下面這樣表格搀矫。不過(guò)在展示表格之前抹沪,我先為大家灌輸兩個(gè)知識(shí)點(diǎn)

1、ppi計(jì)算公式

ppi計(jì)算公式.png

2瓤球、在Android設(shè)備中融欧,dpi 等價(jià)于 ppi

恩,此處請(qǐng)停留10秒......下面展示我繪制的表格:

201612&201701設(shè)備分辨率_統(tǒng)計(jì)分析.png

有兩個(gè)注意點(diǎn):

  1. 表格中上兩行代表的是Android的設(shè)備分辨率及相關(guān)數(shù)據(jù)冰垄,下三行代表的是iOS的設(shè)備分辨率及相關(guān)數(shù)據(jù)
  2. Android屏幕密度為320或480是由谷歌規(guī)定的蹬癌,當(dāng)然這里排除各大廠商自行修改的情況

根據(jù)上述表格我們可以清楚的知道iOS流行的設(shè)備分辨率正好對(duì)應(yīng)Android流行的設(shè)備分辨率,那么知道這又有什么用虹茶?

除了一開始給出結(jié)論的內(nèi)存和適配因素外逝薪,更重要的是可以節(jié)省設(shè)計(jì)資源和工作量。在現(xiàn)在的App開發(fā)中(iOS和Android)蝴罪,有些設(shè)計(jì)師為了保持iOS和Android的體驗(yàn)交互一致董济,可能會(huì)以iPhone手機(jī)為基礎(chǔ)進(jìn)行設(shè)計(jì),包括后期的切圖之類的要门。

不過(guò)根據(jù)上述表格虏肾,我們不是應(yīng)該使用兩套圖嗎廓啊?這里由于在Android設(shè)備中xhdpi和xxhdpi目錄下的圖片顯示效果差異不大,所以完全可以只使用一套圖封豪。

現(xiàn)在我們的設(shè)備中只有一套圖了谴轮,接下來(lái)該怎么為APK瘦身呢?

處理圖片

當(dāng)我們從設(shè)計(jì)師手中得到設(shè)計(jì)稿之后吹埠,之后的工作顯然就是切圖了第步,如果設(shè)計(jì)師切好圖就更好了,得到圖片之后我們一定要記得壓縮缘琅。

如果圖片類型是.png或.jpg的話粘都,我們可以使用tinypng進(jìn)行壓縮;如果圖片類型是.gif的話刷袍,我建議使用PS進(jìn)行壓縮或裁剪翩隧,如果你不會(huì)PS的話,可以讓設(shè)計(jì)師幫忙呻纹。

如果你對(duì)圖片壓縮質(zhì)量不滿意的話堆生,還可以考慮使用不帶alpha值的jpg圖片、9Patch圖片雷酪、同等質(zhì)量下文件更小的WebP圖片格式顽频、或者使用SVG替換某些圖片資源等其他方式。

下面對(duì)于最后兩種方式進(jìn)行簡(jiǎn)要的闡述:

首先是WebP:AndroidStudio自2.3版本之后提供了Convert to WebP的功能太闺,選中res目錄后右擊滑到底部即可看到此功能糯景,下面的引用講述了WebP的概念和支持度:

WebP是Google新推出的影像技術(shù),它可讓網(wǎng)頁(yè)圖檔有效進(jìn)行壓縮省骂,同時(shí)在質(zhì)量相同的情況下蟀淮,WebP格式圖像的體積要比JPEG格式圖像小40%,進(jìn)而讓整體網(wǎng)頁(yè)下載速度加快钞澳。為了改善JPEG的圖片壓縮技術(shù)怠惶,他們使用了一種基于VP8編碼的圖片壓縮器,利用預(yù)測(cè)編碼技術(shù)轧粟,同時(shí)還采用了一種基于RIFF的非常輕量級(jí)的容器策治。這種容器只會(huì)給每張圖片增加20字節(jié),但能讓圖片作者保存他們想要存儲(chǔ)的元數(shù)據(jù)兰吟。

android同樣作為google的產(chǎn)品通惫,minsdk為4.0即api14以上就可以支持webp,但是對(duì)透明的圖片會(huì)存在一些問(wèn)題混蔼,minsdk為4.2.1+即api17可以完美支持webp履腋。
考慮目前市場(chǎng)4.2.1以下的手機(jī)占比已經(jīng)非常稀少,采用webp格式代替jpg、png的方案非匙窈可行悔政。

下面展示一下我司某張圖片png形勢(shì)下和WebP形勢(shì)下各自的大小:

WebP壓縮效果.png

其次是SVG:SVG是可縮放矢量圖形(Scalable Vector Graphics)延旧,它使用XML格式定義圖像谋国,可用于替換APK中的圖標(biāo)

我們開發(fā)者不需要會(huì)如何制作迁沫,這是設(shè)計(jì)師的工作烹卒,當(dāng)然設(shè)計(jì)師也不會(huì)傻乎乎通過(guò)寫代碼的方式繪制圖標(biāo),顯然是使用軟件制作的弯洗。

目前我司也使用了SVG,不過(guò)它的表現(xiàn)形式是阿里巴巴提供的iconfont逢勾,它不僅允許設(shè)計(jì)師自己制作SVG圖片上傳牡整,也提供了百萬(wàn)種圖標(biāo)供選擇。

減少資源

經(jīng)過(guò)上述的方式處理圖片溺拱,想必在圖片質(zhì)量方面已經(jīng)無(wú)計(jì)可施了逃贝,所以我們只能通過(guò)刪除無(wú)用圖片的方式來(lái)為APK瘦身了,當(dāng)然接下來(lái)要介紹的兩種方式可不僅僅是減少圖片迫摔,應(yīng)該稱之為減少資源沐扳。

這里有個(gè)問(wèn)題:為什么會(huì)出現(xiàn)無(wú)用的資源呢?我認(rèn)為有以下幾種情況:

  1. 由于多人協(xié)作開發(fā)句占,沒(méi)有好的規(guī)范沪摄,導(dǎo)致個(gè)人思維嚴(yán)重,隨便添加或刪除資源
  2. 目前公司有好的規(guī)范纱烘,但之前沒(méi)有杨拐,歷史遺留問(wèn)題,沒(méi)人愿意去管理
  3. 上一版需要該資源擂啥,下一版不需要哄陶,然后沒(méi)有刪除

那么,既然知道了原因哺壶,就應(yīng)該想出辦法去解決屋吨,首先是最簡(jiǎn)單的辦法,我們只需要在主模塊的gradle文件中配置shrinkResources即可山宾,具體配置方法如下圖所示:

主模塊Gradle配置.png

這就是為什么說(shuō)它是最簡(jiǎn)單的減少資源方法的原因至扰。

當(dāng)然,因?yàn)楹?jiǎn)單必然存在缺陷资锰,因?yàn)樗荒軓拇虬膽?yīng)用程序和第三方代碼庫(kù)中刪除未被引用的資源渊胸。如果在不同的資源文件夾下面有同名的資源文件,那么就沒(méi)有辦法刪除了台妆,即使該資源真的沒(méi)有被使用翎猛。

所以胖翰,沒(méi)有好的辦法了,目前我能想到的只能是手動(dòng)刪除了切厘,我們可以通過(guò)AndroidStudio提供的Remove Unused Resources功能預(yù)覽刪除真正未使用的資源萨咳,選中res目錄右擊選擇Refactor-Remove Unused Resources...選項(xiàng)之后會(huì)出現(xiàn)下面這樣的圖:

Remove Unused Resources.png

然后根據(jù)查找到結(jié)果,逐條雙擊打開文件疫稿,按快捷鍵fn+option+F7進(jìn)行查找培他,然后在分析是否應(yīng)該刪除,注意:此處定要慎重遗座,務(wù)必自測(cè)R荨!途蒋!猛遍。

另外,我們還可以通過(guò)將某些圖片轉(zhuǎn)換網(wǎng)絡(luò)圖片的方式解決号坡,但是這個(gè)操作也是需要慎重的懊烤,最重要的一點(diǎn)是不能影響用戶的體驗(yàn)。這邊路飛同學(xué)制作了一個(gè)Chrome插件來(lái)幫助我們快速上傳圖片到cdn中宽堆,可以通過(guò)此處下載:joyuploader腌紧。

最后,還有一種辦法:使用AndroidStudio提供的Lint工具對(duì)工程做靜態(tài)代碼檢查畜隶,它不僅可以找出我們?cè)诖a編寫上面的失誤壁肋,還能夠列出那些未被使用的資源,甚至還可以指出哪些地方可能存在內(nèi)存泄漏等等籽慢,功能非常龐大墩划,所以如果工程較大的話,還是比較耗時(shí)的嗡综,當(dāng)然這并不是問(wèn)題乙帮,因?yàn)槲覀兛梢葬槍?duì)某個(gè)模塊執(zhí)行靜態(tài)代碼檢查。我們可以通過(guò)選中菜單欄Analyze-Inspect Code...選項(xiàng)執(zhí)行靜態(tài)代碼檢查极景,執(zhí)行完成的效果圖如下所示:

Lint.png

資源混淆

目前我們不僅在資源(特指圖片)質(zhì)量方面做到了極致察净,在資源數(shù)量方面也做到了極致,看起來(lái)真的到極致了盼樟。其實(shí)不然氢卡,我們還可以使用資源混淆的方式為APK瘦身,通過(guò)壓縮文件內(nèi)容晨缴,減少文件名長(zhǎng)度的方式實(shí)現(xiàn)译秦。

目前比較出名的資源混淆方式是微信的AndResGuard美團(tuán)的修改AAPT,不過(guò)由于美團(tuán)的資源混淆方法非常麻煩,還有如果需要通過(guò)getIdentifier的方式獲取資源時(shí)需要保證這些資源的名字不被混淆筑悴,美團(tuán)很難實(shí)現(xiàn)们拙,所以目前大家都在用微信的資源混淆方式,因?yàn)槲⑿攀褂梅奖愀罅撸姨峁┝税酌麊巍?/p>

下面是我司測(cè)試版APK未使用微信資源混淆和使用了微信資源混淆的差異:

shopandroid-debug.apk.png
shopandroid-debug_signed_7zip_aligned.apk.png

可以清楚的看到砚婆,在使用了微信資源混淆之后,APK減少了0.7MB左右突勇,效果還是十分明顯的装盯。

那么為什么使用了微信資源混淆之后可以實(shí)現(xiàn)APK瘦身呢?下面這兩張圖清楚的展示了瘦身的原因(摘自微信資源混淆官方文檔):

總結(jié)甲馋,安裝包大小減少的原因以下四個(gè):

AndResGuard安裝包減小的原因.png

相對(duì)的埂奈,可得到影響效果的因素有以下幾個(gè):

AndResGuard影響APK大小的因素.png

可以說(shuō),直到現(xiàn)在定躏,我們對(duì)于資源的壓縮猜到了一個(gè)極致账磺,下面是一些針對(duì)于某些資源的壓縮辦法。

其他資源

  1. 如果raw文件夾下有音頻文件共屈,盡量不要使用無(wú)損的音頻格式,比如wav党窜∞忠可以考慮相比于mp3同等質(zhì)量但文件更小的opus音頻格式。
  2. 能不用圖片的就不用圖片幌衣,除了通過(guò)前面提過(guò)的使用9Patch圖矾削、iconfont實(shí)現(xiàn)外,還可以使用shape代碼實(shí)現(xiàn)豁护,也可以考慮引進(jìn)VectorDrawable(矢量圖) 哼凯,從5.0(API等級(jí)21)開始,android開始支持矢量圖楚里。目前矢量圖兼容到API7断部,矢量圖動(dòng)畫兼容到API11。這里就不詳細(xì)講解了班缎。

終于講完了res部分蝴光,碼字好累,接下來(lái)就相對(duì)輕松了达址,首先我們要講解的是classes.dex文件蔑祟。

classes.dex

首先,什么是classes.dex沉唠?classes.dex文件是Android系統(tǒng)的可執(zhí)行文件疆虚,包含應(yīng)用程序的全部操作指令以及運(yùn)行時(shí)數(shù)據(jù)。

這里稍微介紹一下classes.dex文件的生成過(guò)程及對(duì)應(yīng)的命令:

  1. java源代碼 -> class字節(jié)碼:[javac -source 1.6 -target 1.6 com/package1/*.java com/package2/*.java]

  2. class字節(jié)碼 -> jar包:[jar cvf abc.jar com/package1/*.class com/package2/*.class]

  3. jar包 -> dex文件:[dx --dex --output ***/abc.jar ***/abc_dex.jar],***是abc.jar的絕對(duì)路徑径簿。

從jar包到dex文件的過(guò)程是通過(guò)dx工具完成的罢屈,它的目的是使各個(gè)類能夠共享數(shù)據(jù),在一定程度上降低了冗余牍帚,同時(shí)也使文件結(jié)構(gòu)更加緊湊儡遮,實(shí)驗(yàn)表明,dex文件是傳統(tǒng)jar文件大小的50%左右暗赶,具體表現(xiàn)形式可以看下圖:

jar2dex.png

既然dx工具已經(jīng)辦幫我們壓縮了那么多鄙币,那我們還有什么好壓縮的呢?

當(dāng)然有蹂随,因?yàn)閐x工具并沒(méi)有壓縮class的內(nèi)容十嘿,所以我們的源代碼并沒(méi)有得到壓縮,下面我先介紹兩種常見的辦法來(lái)解決這個(gè)問(wèn)題:

  1. 和之前最簡(jiǎn)單的資源壓縮方式一樣岳锁,我們也可以在主模塊的gradle文件中配置minifyEnabled實(shí)現(xiàn)代碼混淆绩衷,從而減小java文件的大小。因?yàn)榛煜蟮拇a將較長(zhǎng)的文件名激率、實(shí)例咳燕、變量、方法名等等做了簡(jiǎn)化乒躺,從而實(shí)現(xiàn)字節(jié)長(zhǎng)度上的優(yōu)化招盲。

  2. 我們也可以使用之前所說(shuō)的AndroidStudio提供的Lint工具執(zhí)行靜態(tài)代碼檢查,進(jìn)而刪除無(wú)用的類嘉冒、方法曹货、變量等。

上面的兩種方式雖然能夠幫助我們減少APK的大小讳推,但是實(shí)際上我們還可以做的更多顶籽。因?yàn)樯厦鎯煞N方式是自動(dòng)化的,所以必然不像人那么智能银觅。

有時(shí)候我們可能遇到這樣的情況:我們引用了一個(gè)第三方類庫(kù)礼饱,但是只用到了其中的幾個(gè)功能,其他的大部分功能一直不用究驴,這不是白白的浪費(fèi)了用戶的流量慨仿,降低了APK的下載轉(zhuǎn)化率么?為了解決這樣的問(wèn)題纳胧,我們必須借助一些工具去找到這樣的類庫(kù)镰吆,比如在文章開頭介紹過(guò)的工具:NimbleDroid,下面是我司APK目前存在的某個(gè)這樣的第三方類庫(kù):

Method Count Of ZXing.png

該類庫(kù)在我司APK中只用到了掃一掃和生成二維碼這兩個(gè)功能跑慕,然而這個(gè)類庫(kù)定義的方法數(shù)竟然有1428万皿,顯然不合理摧找,完全可以抽離其內(nèi)部的掃一掃和生成二維碼代碼,單獨(dú)實(shí)現(xiàn)牢硅。

ReDex

最后介紹一下Facebook開源的一個(gè)減少APK大小以提高性能的工具 -- ReDex蹬耘,它通過(guò)內(nèi)嵌以及清除僵尸代碼這樣的優(yōu)化方式來(lái)減少字節(jié)碼,其主要是對(duì)DEX做了優(yōu)化减余,能夠讓APK運(yùn)行更快综苔,不過(guò)需要多測(cè)試是否會(huì)崩潰。

下面分別是ReDex的教程地址和GitHub地址:

Open-sourcing ReDex: Making Android apps smaller and faster | Engineering Blog | Facebook Code | Facebook

facebook/redex: A bytecode optimizer for Android apps

我個(gè)人由于時(shí)間問(wèn)題位岔,目前還未接入該工具如筛,下面就展示一下網(wǎng)友u012124438的測(cè)試數(shù)據(jù)好了:

ReDex.png

后來(lái)我在使用 Redex 壓縮和優(yōu)化 Android APK一文的幫助下,成功的安裝并使用了ReDex抒抬,但是發(fā)現(xiàn)了以下兩個(gè)問(wèn)題:

  1. 用ReDex處理過(guò)的APK杨刨,其內(nèi)部的META-INF目錄會(huì)被刪除,雖然可以將ReDex處理過(guò)的APK用AndResGuard處理一下擦剑,會(huì)重新出現(xiàn)該目錄妖胀。
  2. 用ReDex處理過(guò)的APK,安裝好之后會(huì)出現(xiàn)Crash的問(wèn)題惠勒,目前我司測(cè)試版APK要Crash三次之后才能正常使用赚抡,而且它對(duì)于我司APK的貢獻(xiàn)只有20~25K,所以并未打算接入纠屋。

resources.arsc

最后就是對(duì)于resources.arsc文件的壓縮處理了涂臣,其實(shí)這里我們也不需要做什么,首先因?yàn)樵撐募涗浀氖琴Y源文件和資源ID的映射關(guān)系巾遭,并沒(méi)有什么值得壓縮的地方窖贤;另外如果真的有值得壓縮的地方尺栖,也只有資源文件的名字了怎抛,不過(guò)這個(gè)早就在之前因?yàn)槲覀兪褂昧宋⑿刨Y源混淆解決了拓瞪,所以此處就不再多講了呀袱。

至此稚照,針對(duì)于APK目錄結(jié)構(gòu)鲫忍,逐條分析如何為APK瘦身已經(jīng)講完了冀墨,接下來(lái)介紹一下其他的壓縮方式刚夺。

其他方式

使用APK Splits構(gòu)建APK

雖然我們上面很好的使用了resource shrinker可以回收一些未使用的資源(v7献丑、v4、google Service 等Libarry資源)侠姑,但有些資源仍然未被清除创橄。

例如:那些未使用的多套替代資源,或者是library內(nèi)部隱患著引用著的資源而我們卻沒(méi)有使用到莽红⊥孜罚或者是我們要根據(jù)用戶的手機(jī)去提供不同版本的APK邦邦,如分辨率(xxhdpi,mhdpi等),so庫(kù)等醉蚁。那么我們可以使用APK Splits大大的減少一些無(wú)用的資源燃辖,這里我們主要參考了http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits文檔。

使用多版本的APK

Multiple APK Support是一個(gè)在Google Play网棍,可以發(fā)布不同的應(yīng)用程序黔龟,分別針對(duì)不同的設(shè)備配置特征。每個(gè)APK是一個(gè)完整的滥玷、獨(dú)立的應(yīng)用程序版本氏身,但他們分享在Google Play相同的應(yīng)用程序清單,必須共享相同的包名和與簽名罗捎。Google Play 會(huì)自動(dòng)給你匹配相應(yīng)的APK观谦,這樣我們的APK 就可以是分不同版本構(gòu)建需要資源文件,從而減小APK的大小桨菜。

資源動(dòng)態(tài)加載

我們可以在項(xiàng)目中使用資源動(dòng)態(tài)加載形式豁状,例如:表情,語(yǔ)言倒得,離線庫(kù)等資源動(dòng)態(tài)加載泻红,減小APK的大小。

支持插件化

未來(lái)對(duì)于一些獨(dú)立業(yè)務(wù)模塊霞掺,可以做成插件化動(dòng)態(tài)加載谊路,用戶需要使用時(shí),只需下載少部分插件菩彬。

使用shape背景

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

使用著色方案

相信你的工程里也有很多selector文件,也有很多相似的圖片只是顏色不同耙旦,通過(guò)著色方案我們能大大減輕這樣的工作量脱羡,減少這樣的文件。

借助于android support庫(kù)可實(shí)現(xiàn)一個(gè)全版本兼容的著色方案免都,參考代碼:DrawableLess.java

其他方式...

總結(jié)

如果你不是一個(gè)Android開發(fā)人員锉罐,對(duì)于之前的闡述可能非常模糊,并不能明顯的表現(xiàn)出APK瘦身這件事情的意義绕娘,下面我就來(lái)總結(jié)一下:

首先脓规,針對(duì)于我司測(cè)試版APK做了哪些應(yīng)用?

  1. 字體文件使用Glyphs進(jìn)行壓縮险领,圖片使用tinypng進(jìn)行壓縮

  2. 只是用一套so文件

  3. 只使用一套圖

  4. 使用WebP圖片或SVG圖片替換某些PNG或JPG圖片

  5. 使用Google提供的Gradle插件實(shí)現(xiàn)代碼混淆和資源混淆

  6. 借助NimbleDroid侨舆、AS Anylze/Lint工具分析查找刪除不需要的代碼或資源

  7. 使用微信提供的資源混淆工具(處于穩(wěn)定性測(cè)試階段)

  8. 使用Facebook提供的ReDex工具(處于調(diào)研階段)

其次升酣,APK瘦身的效果如何?

這里我們就直接看圖好了:

APK瘦身效果.png

可以明顯的發(fā)現(xiàn)态罪,我司的APK越來(lái)越小了噩茄,所以說(shuō),這個(gè)工作是很有意義的复颈。

最后绩聘,做一下競(jìng)品分析?

競(jìng)品分析.png

根據(jù)上面圖表耗啦,可以發(fā)現(xiàn)我們的APK的大小是十分有優(yōu)勢(shì)的凿菩,能夠很好的提高下載轉(zhuǎn)化率。而iOS那邊顯然就比較大了帜讲,雖然兩者之間不能比較衅谷,但是還是可以進(jìn)行一系列優(yōu)化的。

忠告

最后的最后似将,我想對(duì)大家說(shuō):在APK瘦身的道路上获黔,一定要掌握好,安排好事情的優(yōu)先級(jí)在验,如果目前要做的事情玷氏、要優(yōu)化的方面比較復(fù)雜,不僅需要花費(fèi)很長(zhǎng)的時(shí)間腋舌,而且最終效果也不明顯盏触,可以考慮之后再做,甚至不做块饺。

參考鏈接

  1. 【Android技術(shù)專題】APK瘦身看這一篇文章就夠了
  2. 那些你不知道的 APK 瘦身赞辩,讓你的 APK 更小
  3. Android 性能優(yōu)化系列 之 apk 瘦身
  4. APK文件結(jié)構(gòu)和安裝過(guò)程
  5. Android開發(fā)之資源目錄assets與res/raw的區(qū)別分析
  6. Android開發(fā)之a(chǎn)ssets目錄下資源使用總結(jié)
  7. Android開發(fā):最全面、最易懂的Android屏幕適配解決方案
  8. 是時(shí)候使用 webp 給 apk 瘦身了授艰!
  9. Dex文件格式詳解
  10. Android應(yīng)用瘦身辨嗽,從18MB到12.5MB
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市想诅,隨后出現(xiàn)的幾起案子召庞,更是在濱河造成了極大的恐慌岛心,老刑警劉巖来破,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異忘古,居然都是意外死亡徘禁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門髓堪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)送朱,“玉大人娘荡,你說(shuō)我怎么就攤上這事∈徽樱” “怎么了炮沐?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)回怜。 經(jīng)常有香客問(wèn)我大年,道長(zhǎng),這世上最難降的妖魔是什么玉雾? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任翔试,我火速辦了婚禮,結(jié)果婚禮上复旬,老公的妹妹穿的比我還像新娘垦缅。我一直安慰自己,他們只是感情好驹碍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布壁涎。 她就那樣靜靜地躺著,像睡著了一般志秃。 火紅的嫁衣襯著肌膚如雪粹庞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天洽损,我揣著相機(jī)與錄音庞溜,去河邊找鬼。 笑死碑定,一個(gè)胖子當(dāng)著我的面吹牛流码,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播延刘,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼漫试,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了碘赖?” 一聲冷哼從身側(cè)響起驾荣,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎普泡,沒(méi)想到半個(gè)月后播掷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撼班,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年歧匈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砰嘁。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡件炉,死狀恐怖勘究,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情斟冕,我是刑警寧澤口糕,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站磕蛇,受9級(jí)特大地震影響走净,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜孤里,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一伏伯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捌袜,春花似錦说搅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至霍衫,卻和暖如春候引,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背敦跌。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工澄干, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柠傍。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓麸俘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親惧笛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子从媚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 本文來(lái)自尚妝Android團(tuán)隊(duì)青峰發(fā)表于尚妝博客 APK瘦身探索 最近幾周一直在研究如何為APK瘦身,折騰了很久患整,...
    尚妝產(chǎn)品技術(shù)刊讀閱讀 1,786評(píng)論 1 23
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,070評(píng)論 25 707
  • 本文會(huì)不定期更新拜效,推薦watch下項(xiàng)目。如果喜歡請(qǐng)star各谚,如果覺得有紕漏請(qǐng)?zhí)峤籭ssue紧憾,如果你有更好的點(diǎn)子可以...
    天之界線2010閱讀 18,212評(píng)論 19 153
  • 1、 前言 如果你對(duì)App優(yōu)化比較敏感嘲碧,那么Apk安裝包的大小就一定不會(huì)忽視稻励。關(guān)于瘦身的原因父阻,大概有以下幾個(gè)方面:...
    未來(lái)的理想閱讀 11,070評(píng)論 4 39
  • 如果你問(wèn)我 是從那一刻愛上北方的愈涩? 我會(huì)回答:是在逃離北方之后望抽。 我不知道四季分明也是一種精彩 我不知道漫天的陽(yáng)光...
    栗尋閱讀 318評(píng)論 0 3