如何進行APK瘦身

本篇文章已授權(quán)微信公眾號guolin_blog(郭霖)獨家發(fā)布

轉(zhuǎn)載請注明出處:http://www.reibang.com/p/7b623fed6302

APK的大小對于app載入速度、占用內(nèi)存大小以及耗電量有著很大的影響蚜点。一般而言,用戶并不太喜歡下載APK體積太大的app厂镇。尤其是對于流量、手機內(nèi)存有限的用戶來講残黑,太大的APK往往會讓他們望而卻步。那么如何讓APK的體積降下來呢?

了解APK結(jié)構(gòu)

想要對APK進行瘦身雏亚,你必須得先了解APK的組成結(jié)構(gòu)胖笛,只有了解APK由哪些部分組成,你才能有所針對性的進行APK瘦身辟汰。
APK主要由以下幾部分組成:

  • META-INF/ :包含了簽名文件CERT.SF凑术、CERT.RSA鹿鳖,以及 manifest 文件MANIFEST.MF命满。
  • assets/ : 存放資源文件杂抽,這些資源不會被編譯成二進制赡矢。
  • lib/ :包含了一些引用的第三方庫。
  • resources.arsc :包含res/values/中所有資源界轩,例如strings,styles报辱,以及其他未被包含在resources.arsc中的資源路徑信息,例如layout 文件慢睡、圖片等。
  • res/ :包含res中沒有被存放到resources.arsc的資源袒啼。
  • classes.dex :經(jīng)過dx編譯能被android虛擬機理解的Java源碼文件。
  • AndroidManifest.xml :這個不用解釋

我們可以通過android studio --> build --> Analyze APK 來查看一下上述各個部分文件大小情況

analyze.png

從上圖來看,占用空間的主要是代碼蚓再、res 和 lib 滑肉,因為我的assets中沒有放文件,所以看起來并沒有占用什么空間摘仅,其實assets中文件放的多靶庙,一樣會占用很大空間。所以APK瘦身時实檀,主要就從代碼惶洲、reslibassets這幾個方面考慮膳犹。

減少資源文件數(shù)量和大小

APK瘦身的一個很簡單的辦法就是減少資源文件的數(shù)量和大小恬吕,本節(jié)就來討論一些常用的方法。

去除無用資源
  • 使用lint工具來檢測res/中是否有沒有使用到的資源
  • 然而對于一些第三方庫來說须床,使用lint可能無法檢測到铐料,我們可以使用shrinkResources來刪除庫文件中無用的資源,配合proguard壓縮代碼使用
android {
    // Other settings

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
  • 移除未使用的備用資源豺旬。例如對于一些第三庫來說钠惩,因為國際化的問題,它們可能會支持了幾十種語言族阅,但我們的應(yīng)用可能只需要支持中文就行了篓跛,這時候我們就可以使用resConfigresConfigs來解決。
    下面這段代碼展示了如何將語言資源限定為僅支持中文:
android {
    defaultConfig {
        ...
        resConfigs "zh"
    }
}
使用最小化資源的庫

我們開發(fā)項目的時候坦刀,經(jīng)常會用到許多第三方庫愧沟,但第三方庫往往可能會很大,那怎么來進行壓縮呢鲤遥?

  • 使用ProGuard壓縮代碼沐寺,然后配合shrinkResources使用,方法見上面shrinkResources的使用盖奈。
  • 然而ProGuard只能壓縮庫本身的一些沒有用到的代碼混坞,但庫內(nèi)部本身可能仍依賴了其他的第三方庫,對于這些庫ProGuard卻無法進行有效去除钢坦。
    很多第三方庫會提供多種版本究孕,例如完整版、精簡版爹凹、針對某個功能的特殊版蚊俺,你只需要選擇能包含你需要功能的體積最小版本庫。當然如果你能獲得源碼逛万,自己提煉出你所需要的功能就更好了泳猬。
只支持特定屏幕密度

Android支持多種屏幕密度設(shè)備批钠,Android 4.4以上版本支持包括:ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpi and xxxhdpi。盡管Android支持了這么多屏幕密度得封,但你并不需要全部支持埋心,你可以根據(jù)你的需求來選擇支持。

使用drawable 對象

對于一些簡單的images可以不使用圖片忙上,使用Drawable XML來進行繪制拷呆。

復用資源

對于相似的一些Image可以復用同一張圖片。

  • 形狀一樣疫粥,但顏色茬斧、陰影有區(qū)別的Image;在 Android 5.0 (API level 21)以及以上版本梗逮,可以使用android:tint, tintMode等屬性去調(diào)整项秉,在Android 5.0以下可以使用ColorFilter來調(diào)整。
  • 形狀顏色一樣慷彤,但角度不一樣的Image娄蔼;可以使用rotate等來調(diào)整角度達到復用效果。例如:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_thumb_up"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromDegrees="180" />
代碼渲染

你也可以通過代碼渲染來代替使用圖片底哗,例如使用自定義View繪制岁诉。圖片減少了,APK自然瘦身了跋选。

緊縮PNG文件

AAPT工具會在構(gòu)建期間自動對res/drawable/文件夾下的PNG圖片資源做無損壓縮涕癣。例如,一張true-color的PNG圖片前标,如果它實際需要的顏色不大于256種坠韩,那么就有可能會被轉(zhuǎn)換成一張8位的調(diào)色板圖片(PNG8)。轉(zhuǎn)換之后的圖片質(zhì)量未減卻只占用更小的內(nèi)存候生。

壓縮PNG和JPG

你可以使用pngcrush, pngquantzopflipng來壓縮PNG圖片。
使用packJPGguetzli 來壓縮JPG圖片绽昼。

使用WebP

你可以使用 WebP 來代替JPG和PNG圖片唯鸭。WebP 保留了JPG和PNG優(yōu)點的同時,能提供更好的壓縮硅确,達到更小的體積目溉。
你可以將已經(jīng)有的JPG、PNG菱农、GIF等直接轉(zhuǎn)為WebP圖片缭付,方法請參考:Create WebP Images Using Android Studio.

注意:啟動圖標最好不要用WebP,因為谷歌商店只接受啟動圖片格式為PNG的APK循未。

使用矢量圖形

你可以使用矢量圖形來繪制分辨率無關(guān)圖標及其他可伸縮媒體文件陷猫。整個屏幕那么大的清晰圖片,如果使用矢量圖可能只需要100-byte大小。
然而使用矢量圖形會讓系統(tǒng)花更多的時間來進行繪制绣檬,所以最好只在比較小的images上使用矢量圖足陨。

將矢量圖形用于動畫圖像

不要使用AnimationDrawable來創(chuàng)建幀動畫,否則每一幀就用一張圖片會占用大量的空間娇未。這個時候你應(yīng)該使用AnimatedVectorDrawableCompat墨缘。

減少本地代碼和Java代碼

這兒有幾種方法來減小Java代碼和本地代碼庫的大小。

刪除不必要的生成代碼

要確保能夠了解自動生成的代碼用途零抬,例如有很多的protocol buffer tools會自動生成大量你可能用不到的代碼镊讼。

避免使用枚舉

一個單獨的枚舉可以將apk增加1.0 到1.4 KB大小,對于復雜的系統(tǒng)或者共享庫來說平夜,累積下來可能會增加相當大的APK體積蝶棋。
如果可能的話,可以考慮使用@IntDef注解和ProGuard來剝離枚舉并將它們轉(zhuǎn)換為整數(shù)褥芒。這種類型轉(zhuǎn)換保留了枚舉的類型安全優(yōu)勢嚼松。

減少本地二進制文件的大小

如果你的APP使用native code 和 Android NDK,那么可以通過兩種方法優(yōu)化代碼锰扶,達到減小APK大小的效果献酗。

  • 刪除Debug符號
    使用Android NDK中提供的arm-eabi-strip工具來移除Native庫中不必要的Debug符號。
  • 避免提取本地庫
    在 Android 6.0 之前坷牛, so 文件會壓縮到 apk 中罕偎,系統(tǒng)在安裝應(yīng)用的時候,會把 so文件解壓到 data 分區(qū)京闰,這樣同一個 so 文件會有兩份存在颜及,一個在 apk 中一個在 data 區(qū)中, 導致多占用了一倍空間蹂楣。 從 Android 6.0 開始俏站,你可以在 AndroidManifest.xml 中使用一個新的屬性:
<application
 android:extractNativeLibs=”false”
 ...
>

該屬性告訴系統(tǒng),不要把 so 文件從 apk 中解壓出來了痊土,并且修改 System.loadLibrary 調(diào)用直接從 apk 中打開 so 文件肄扎。

維護多個精簡版APK

你的APP中可能會包含許多用戶根本不會使用的內(nèi)容,例如區(qū)域和語言信息赁酝。你可以根據(jù)屏幕尺寸或GPU紋理支持等因素針對性提供不同版本的APK犯祠。當用戶下載APK的時候,會根據(jù)手機的特性和設(shè)置有針對性的下載特定版本APK酌呆,這樣的話用戶就不會下載到他根本不需要的內(nèi)容衡载。
上面的話是從官網(wǎng)翻譯過來的,看不太懂沒關(guān)系隙袁,其實就是按需提供資源支持痰娱,根據(jù)手機的不同提供不同版本的APK弃榨,我們直接來看例子

android {
  ...
  splits {
    //根據(jù)屏幕像素密度來創(chuàng)建多個APK
    density {
      enable true
      //根據(jù)屏幕密度創(chuàng)建兩個版本APK,"mdpi", "hdpi"
      reset()
      include "mdpi", "hdpi"
    }
    //根據(jù)手機cpu指令集分類創(chuàng)建多個APK
    abi {
      enable true
      //創(chuàng)建 "x86", "x86_64"兩個版本APK
      reset()
      include "x86", "x86_64"
    }
  }
}

我們來編譯一下APK看下結(jié)果

multipleApk.png

我們可以看到生成了6個APK猜揪,為什么是6個呢惭墓?
首先屏幕密度有三個版本(mdpi, x86_64,gralde還會生成一個包含所有屏幕密度資源的默認版本),ABI指令集有兩個版本(gralde默認編譯不會添加包含所有ABI指令集版本的APK而姐,如果你想添加腊凶,需要在abi代碼塊中加上universalApk true),它們兩兩組合為6種拴念。每個APK里只會包含它對應(yīng)的資源钧萍,例如app-hdpiX86-debug.apk中只會存在屏幕密度為hdpi的資源以及X86的庫文件。
如果你的手機cpu指令集是x86政鼠,屏幕密度為hdpi风瘦,那么你會下載到app-hdpiX86-debug.apk

你可以通過Configure APK SplitsMaintaining Multiple APKs來進一步了解相關(guān)內(nèi)容公般。

參考資料
https://developer.android.google.cn/topic/performance/reduce-apk-size
https://developer.android.google.cn/studio/build/shrink-code
https://developer.android.google.cn/studio/write/lint
http://www.reibang.com/p/0eae3f13dcd6
http://blog.chengyunfeng.com/?p=895

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末万搔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子官帘,更是在濱河造成了極大的恐慌瞬雹,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刽虹,死亡現(xiàn)場離奇詭異酗捌,居然都是意外死亡,警方通過查閱死者的電腦和手機涌哲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門胖缤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阀圾,你說我怎么就攤上這事哪廓。” “怎么了初烘?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵涡真,是天一觀的道長。 經(jīng)常有香客問我账月,道長综膀,這世上最難降的妖魔是什么澳迫? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任局齿,我火速辦了婚禮,結(jié)果婚禮上橄登,老公的妹妹穿的比我還像新娘抓歼。我一直安慰自己讥此,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布谣妻。 她就那樣靜靜地躺著萄喳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蹋半。 梳的紋絲不亂的頭發(fā)上他巨,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音减江,去河邊找鬼染突。 笑死,一個胖子當著我的面吹牛辈灼,可吹牛的內(nèi)容都是我干的份企。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巡莹,長吁一口氣:“原來是場噩夢啊……” “哼司志!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起降宅,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤骂远,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后钉鸯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吧史,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年唠雕,在試婚紗的時候發(fā)現(xiàn)自己被綠了贸营。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡岩睁,死狀恐怖钞脂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捕儒,我是刑警寧澤冰啃,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站刘莹,受9級特大地震影響阎毅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜点弯,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一扇调、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抢肛,春花似錦狼钮、人聲如沸碳柱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莲镣。三九已至,卻和暖如春涎拉,著一層夾襖步出監(jiān)牢的瞬間瑞侮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工鼓拧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留区岗,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓毁枯,卻偏偏與公主長得像慈缔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子种玛,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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