減少apk體積

[TOC]

首先說下apk體積減小的必要性

減小apk的安裝時間,增加用戶留存,減少CDN流量費用

再這之前,先來看看apk的結構,以微信apk為例,用Android studio打開

image

可以看到APK由以下主要部分組成:

文件/目錄 描述
lib 存放so文件喉钢,可能會有armeabi、armeabi-v7a杖剪、arm64-v8a服赎、x86榜跌、x86_64什黑、mips起惕,大多數(shù)情況下只需要支持armabi與x86的架構即可涡贱,如果非必需,可以考慮拿掉x86的部分
assets 應用的資源文件
r 這是經(jīng)過proguard的資源文件
class*.dex classes文件是Java Class惹想,被DEX編譯后可供Dalvik/ART虛擬機所理解的文件格式
META_INF 它包含了APK中所有文件的簽名摘要等信息,其中MANIFEST.MF的內(nèi)容是對apk每個文件進行摘要然后base64一下,進行存儲问词。

CERT.SF內(nèi)容是對MANIFEST.MF中的每條內(nèi)容進行進行摘要然后base64一下。

CERT.RSA就是一個pkcs7格式 der編碼的證書文件,可以通過openssl獲取內(nèi)容,這里會把CERT.SF文件用私鑰計算出簽名然后寫入CERT.RSA,

META_INF具體內(nèi)容可以參考[Android簽名機制(http://blog.csdn.net/jiangwei0910410003/article/details/50402000)
resources.arsc 編譯后的二進制資源
AndroidManifest.xml Android的清單文件

在介紹怎么做之前嘀粱,先來大概介紹一下App的資源是怎么被打進APK包里的激挪。Android構建工具鏈使用AAPT工具來對資源進行處理,來看下圖(圖片來源于Build Workflow):
[圖片上傳中...(image.png-293ad-1519886265335-0)]

下面來說下具體減少apk size的方法

一. 減少資源的數(shù)量和大小,主要有一下幾個方面

1.使用drawable(xml中使用<shape>標簽生成drawable對象)替換靜態(tài)圖片資源,減少apk的大小

??比如

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <stroke
        android:width="2dp"
        android:color="#2dcaff" />
    
    <gradient 
        android:startColor="@color/transparent"
        android:endColor="@color/transparent"/>
</shape>

??使用Drawable有什么好處锋叨?

???很方便得到一個矩形垄分,圓,橢圓娃磺,圓環(huán)薄湿,很容易維護和修改
???很方便實現(xiàn)圓角,漸變(線性漸變偷卧,徑向漸變豺瘤,掃描漸變)
???代替圖片作為 View 的背景,減少 apk 的體積(減少 apk 體積最明顯最有效的步驟就是去掉圖片)
???大圖片耗內(nèi)存听诸,使用 Drawable 節(jié)省內(nèi)存坐求,Android 本身對 Drawable 做了很好的優(yōu)化(內(nèi)存優(yōu)化需要考慮)

??什么情況下選擇使用Drawable,而不是使用一張圖蛇更,反之呢瞻赶?

???理論上能用 Drawable 的地方就用 Drawable
???如果能夠通過 shape 標簽就能定義的幾何圖形就能滿足需求,就不用圖片來表示
???漸變類型的背景也盡量使用 shape 來實現(xiàn)
???不規(guī)則的派任,復雜的圖形還是只能使用圖片砸逊,比如要一個表示手機的圖標,一個人的頭像
???有些特殊拉升效果需要使用 .9.png 圖片(盡可能的小吧掌逛,越小越省內(nèi)存)

2.刪除未使用的資源

??使用lint工具檢測未使用的資源,
??刪除未使用的資源:主要通過shrinkresource編譯時優(yōu)化無用資源师逸,我以前以為這個關鍵字是刪??除無用資源,其實并非這樣豆混,它只是把無用資源替為一個小的虛擬的文件(背景全黑)篓像,并非刪除它,
??設置了shrinkresource的編譯的日志如下
??Skipped unused resource res/drawable-xhdpi-v4/ic_launcher.png: 4366 bytes (replaced with small dummy file of size 67 bytes)

2.圖片優(yōu)化

為了支持Android設備DPI的多樣化([l|m|tv|h|x|xx|xxx]dpi)以及用戶對高質(zhì)量UI的期待动知,美團App中使用了大量的圖片,在Android下支持很多格式的圖片员辩,例如:PNG盒粮、JPGWebP奠滑,那我們該怎么選擇不同類型的圖片格式呢丹皱? 在Google I/O 2016中提到了針對圖片格式的選擇,來看下圖(圖片來源于Image compression for Android developers):

image

通過上圖可以看出一個大概圖片格式選擇的方法宋税。如果能用VectorDrawable來表示的話優(yōu)先使用VectorDrawable摊崭,如果支持WebP則優(yōu)先用WebP,而PNG主要用在展示透明或者簡單的圖片杰赛,而其它場景可以使用JPG格式呢簸。針對每種圖片格式也有各類的優(yōu)化手段和優(yōu)化工具

??使用矢量圖片

???可以使用矢量圖形來創(chuàng)建獨立于分辨率的圖標和其他可伸縮圖片。使用矢量圖片能夠有效的減少App中圖片所占用的大小乏屯,矢量圖形在Android中表示為VectorDrawable對象根时。 使用VectorDrawable對象,100字節(jié)的文件可以生成屏幕大小的清晰圖像瓶珊,但系統(tǒng)渲染每個VectorDrawable對象需要大量的時間啸箫,較大的圖像需要更長的時間才能出現(xiàn)在屏幕上。 因此只有在顯示小圖像時才考慮使用矢量圖形伞芹。有關使用VectorDrawable的更多信息,請參閱 Working with Drawables蝉娜。也可參考 Android使用矢量圖-簡述

??使用WebP

???如果App的minSdkVersion高于14(Android 4.0+)的話唱较,可以選用WebP格式,因為WebP在同畫質(zhì)下體積更姓俅ā(WebP支持透明度南缓,壓縮比比JPEG更高但顯示效果卻不輸于JPEG,官方評測quality參數(shù)等于75均衡最佳)荧呐, 可以通過PNG到WebP轉換工具來進行轉換汉形。當然Android從4.0才開始WebP的原生支持,但是不支持包含透明度倍阐,直到Android 4.2.1+才支持顯示含透明度的WebP概疆,在筆者使用中是判斷當前App的minSdkVersion以及圖片文件的類型(是否為透明)來選用是否適用WebP。見下面的代碼片段:

boolean isPNGWebpConvertSupported() {
    if (!isWebpConvertEnable()) {
        return false
    }

    // Android 4.0+
    return GradleUtils.getAndroidExtension(project).defaultConfig.minSdkVersion.apiLevel >= 14
    // 4.0
}

boolean isTransparencyPNGWebpConvertSupported() {
    if (!isWebpConvertEnable()) {
        return false
    }

    // Lossless, Transparency, Android 4.2.1+
    return GradleUtils.getAndroidExtension(project).defaultConfig.minSdkVersion.apiLevel >= 18
    // 4.3
}

def convert() {
    String resPath = "${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/res/merged/${variant.dirName}"
    def resDir = new File("${resPath}")
    resDir.eachDirMatch(~/drawable[a-z0-9-]*/) { dir ->
        FileTree tree = project.fileTree(dir: dir)
        tree.filter { File file ->
            return (isJPGWebpConvertSupported() && (file.name.endsWith(SdkConstants.DOT_JPG) || file.name.endsWith(SdkConstants.DOT_JPEG))) || (isPNGWebpConvertSupported() && file.name.endsWith(SdkConstants.DOT_PNG) && !file.name.endsWith(SdkConstants.DOT_9PNG))
        }.each { File file ->
            def shouldConvert = true
            if (file.name.endsWith(SdkConstants.DOT_PNG)) {
                if (!isTransparencyPNGWebpConvertSupported()) {
                    shouldConvert = !Imaging.getImageInfo(file).isTransparent()
                }
            }
            if (shouldConvert) {
                WebpUtils.encode(project, webpFactorQuality, file.absolutePath, webp)
            }
        }
    }
}

??減少動畫幀

???再不影響用戶體驗的情況下,可適當?shù)臏p少幀率,進而就減少了幀數(shù),減少資源




二.減少原生和Java代碼

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

??如果你的應用使用原生代碼和Android NDK峰搪,你還可以通過優(yōu)化代碼來減小應用的大小岔冀。兩個有用的技術是刪除調(diào)試符號和提取原生庫。

???. 刪除調(diào)試符號

???? 如果你的應用程序正在開發(fā)中并仍需要調(diào)試概耻,則使用調(diào)試符號很有意義使套。 使用Android NDK中提供的arm-eabi-strip工具從本機庫中刪除不必要的調(diào)試符號罐呼。 之后,你可以編譯你的發(fā)行版侦高。

???. 避免提取原生庫

??? ?將.so文件存儲在APK中未壓縮的文件嫉柴,并在應用清單的<application> </application>元素中將android:extractNativeLibs標記設置為false。 這將防止 PackageManager在安裝過程中將.so文件從APK復制到文件系統(tǒng)奉呛,并且將具有使你的應用程序的delta更新更小的額外好處计螺。

??混淆(java代碼):

???這里不細說混淆了,可以參考這邊文章,我覺得寫的很好Android混淆,個人再補充點混淆規(guī)則之刪除日志

-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int w(...);
    public static int d(...);
    public static int v(...);
    public static int i(...);
}

上面的代碼加到混淆配置文件里面,可以刪除log日志,但是前提是optimize開啟, 不要加-dontoptimize, 之前筆者一直加了上面的代碼,但是日志依然有,究其原因時因為getDefaultProguardFile('proguard-android.txt'),
這是Android默認的混淆文件,這個文件里面有-dontoptimize,所以一直失敗,可以使用proguard-android-optimize.txt這個配置文件

三.resources.arsc的優(yōu)化

resources.arsc是編譯之后的二進制資源,主要維護者資源名字,資源id,資源路徑,資源類型,以及字符串資源的值等等,所以直接參考騰訊的方案安裝包立減1M--微信Android資源混淆打包工具,其主要原理就是將名字和路徑變短,類似于下面的
R.string.name -> R.string.a
res/drawable/icon -> r/s/a

(參考文檔)https://tech.meituan.com/android-shrink-overall-solution.html

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市侧馅,隨后出現(xiàn)的幾起案子危尿,更是在濱河造成了極大的恐慌,老刑警劉巖馁痴,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谊娇,死亡現(xiàn)場離奇詭異,居然都是意外死亡罗晕,警方通過查閱死者的電腦和手機济欢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來小渊,“玉大人法褥,你說我怎么就攤上這事〕晏耄” “怎么了半等?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長呐萨。 經(jīng)常有香客問我杀饵,道長,這世上最難降的妖魔是什么谬擦? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任切距,我火速辦了婚禮,結果婚禮上惨远,老公的妹妹穿的比我還像新娘谜悟。我一直安慰自己,他們只是感情好北秽,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布葡幸。 她就那樣靜靜地躺著,像睡著了一般羡儿。 火紅的嫁衣襯著肌膚如雪礼患。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音缅叠,去河邊找鬼悄泥。 笑死,一個胖子當著我的面吹牛肤粱,可吹牛的內(nèi)容都是我干的弹囚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼领曼,長吁一口氣:“原來是場噩夢啊……” “哼鸥鹉!你這毒婦竟也來了?” 一聲冷哼從身側響起庶骄,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤毁渗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后单刁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灸异,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年羔飞,在試婚紗的時候發(fā)現(xiàn)自己被綠了肺樟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡逻淌,死狀恐怖么伯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卡儒,我是刑警寧澤田柔,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站骨望,受9級特大地震影響凯楔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锦募,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邻遏。 院中可真熱鬧糠亩,春花似錦、人聲如沸准验。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糊饱。三九已至垂寥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背滞项。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工狭归, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人文判。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓过椎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親戏仓。 傳聞我的和親對象是個殘疾皇子疚宇,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,501評論 25 707
  • 最近幾周一直在研究如何為APK瘦身,折騰了很久赏殃,是時候寫篇博客總結一下了敷待,雖然已經(jīng)準備了下周一要在客戶端周會分享用...
    風清袖一閱讀 1,040評論 1 10
  • 本文來自尚妝Android團隊青峰發(fā)表于尚妝博客 APK瘦身探索 最近幾周一直在研究如何為APK瘦身,折騰了很久仁热,...
    尚妝產(chǎn)品技術刊讀閱讀 1,778評論 1 23
  • 生活需要一種儀式感 出生榜揖,在襁褓中誕生,一堆人圍著你笑股耽。 滿月根盒,一堆人圍著你轉,怕你喝不飽物蝙,吃不飽炎滞,睡不夠。 學會...
    stitchyan閱讀 250評論 0 0
  • 生活就像鏈條一樣環(huán)環(huán)相扣诬乞,不同的是册赛,有人把它編織成勒住脖頸的枷鎖,有人把它編織成攀越高山的藤蔓震嫉。
    活色生香徐馬懿閱讀 205評論 0 0