安卓減小APP安裝包的大小

目錄


一、分析app大小

1.使用Android Studio2.2新功能直接分析APK的大小

Build > Analyz APK

Paste_Image.png

 

2.各個文件介紹

assets:存放一些配置文件
res:資源文件,圖片、字符串、xml等
classes.dex:字節碼文件
resources.arsc:編譯後的二進制資源文件
META-INF:存放的是簽名信息,用來保證apk包的完整性和系統的安全。
接下來就從classes.dex , lib , assets下入手。


二、app 體積減小方案

1.使用一套資源

對於絕大對數APP來說,只需要取一套設計圖就足夠了。鑑於現在分辨率的趨勢,建議取1280 * 720p的資源,放到xxhdpi目錄。相對於多套資源,只使用720P的一套資源,在視覺上差別不大,但卻能顯著的減少資源佔用大小。

 

Paste_Image.png

注意:單套圖導致的壓縮和放大,對性能的影響顯而易見。權衡利弊。


2.開啓minifyEnabled混淆代碼

在gradle使用minifyEnabled進行Proguard混淆的配置,可大大減小APP大小:

android {
    buildTypes {
        release {
            minifyEnabled true
        }
    }
}

在proguard中,是否保留符號表對APP的大小是有顯著的影響的,可酌情不保留,但是建議儘量保留用於調試。

3.開啓shrinkResources去除無用資源

在gradle使用shrinkResources去除無用資源,效果非常好。

android {
    buildTypes {
        release {
            shrinkResources true
        }
    }
}

注意:在release下可能會引發Resources$NotFoundException: Resource ID #0x4,把有用的資源移除掉了。添加了shrinkResources true打完包時候要多測一測。
解決辦法:
方案一
放棄使用shrinkResources true
方案二
參考google關於shrink resource
新建 res/raw/keep.xml後加入如下示例:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*,@drawable/icon"
    tools:discard="@layout/unused2" />

保留文件規則簡單介紹,資源文件相對路徑加上圖片文件名(不需要擴展名)
執行 ./gradlew clean assembleRelease –info|grep “Skipped unused resource” 觀察是否安全圖片給壓縮同時檢查解壓縮後文件是否爲0


4.刪除無用的語言資源以及圖片資源

大部分應用其實並不需要支持幾十種語言的國際化支持。還好強大的gradle支持語言的配置,比如國內應用只支持中文

android {
    defaultConfig {
        resConfigs "zh"
        resConfigs "nodpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"
    }
}

5.對圖片進行無損壓縮

android打包本身會對png進行無損壓縮,所以使用像tinypng這樣的有損壓縮是有必要的。
重點是Tinypng使用智能有損壓縮技術,以儘量少的失真換來圖片大小的銳減,效果非常好,強烈推薦。


6.使用jpg格式

如果對於非透明的大圖,jpg將會比png的大小有顯著的優勢,雖然不是絕對的,但是通常會減小到一半都不止。
在啓動頁,活動頁等之類的大圖展示區採用jpg將是非常明智的選擇。


7.使用webp格式

一種圖片文件格式,在相同壓縮標準下,webp的有損壓縮能比jpg小25-34%。webp支持透明度,壓縮比比jpg更高但顯示效果卻不輸於jpg,官方評測quality參數等於75均衡最佳。
相對於jpg、png,webp作爲一種新的圖片格式,限於android的支持情況暫時還沒用在手機端廣泛應用起來。從Android 4.0+開始原生支持,但是不支持包含透明度,直到Android 4.2.1+才支持顯示含透明度的webp,使用的時候要特別注意。使用Fresco支持webp格式圖片。
如果在API<14的系統也要支持webP圖片加入。

// 在API < 14的系統如也要支持 webP圖片的話加入
compile 'com.facebook.fresco:animated-base-support:0.12.0'
// 支持Gif圖片,需加入
compile 'com.facebook.fresco:animated-gif:0.12.0'
// 支持webP圖片的動態圖,需加入
compile 'com.facebook.fresco:animated-webp:0.12.0'
// 支持webP圖片的靜態圖,需加入
compile 'com.facebook.fresco:webpsupport:0.12.0'

常用的webp轉換工具:XnConvet , 智圖 , ISparta


8.縮小大圖

如果經過上述步驟之後,你的工程裏面還有一些大圖,考慮是否有必要維持這樣的大尺寸,是否能適當的縮小。
事實上,由於設計師出圖的原因,我們拿到的很多圖片完全可以適當的縮小而對視覺影響是極小的。


9.覆蓋第三庫裏的大圖

有些第三庫裏引用了一些大圖但是實際上並不會被我們用到,就可以考慮用1x1的透明圖片覆蓋。
你可能會有點不舒服,因爲你的drawable下竟然包含了一些莫名其妙的名稱的1x1圖片…

1×1像素圖片.png


10. 刪除armable-v7包下的so

CPU(7) ABI
ARMV5 armeabi
ARMV7 armeabi-v7a
X86 X86
MIPS mips
ARMV8 arm64-v8a
MIPS64 mips64
x86_64 x86_64

Android 目前支持的CPU架構和對應的二進制接口ABI (Application Binary Interface)

CPU(7) ABI
ARMV5 armeabi
ARMV7 armeabi-v7a
X86 X86
MIPS mips
ARMV8 arm64-v8a
MIPS64 mips64
x86_64 x86_64

基本上armable的so也是兼容armable-v7的,armable-v7a的庫會對圖形渲染方面有很大的改進,如果沒有這方面的要求,可以精簡。
這裏不排除有極少數設備會Crash,可能和不同的so有一定的關係,請大家務必測試周全後再發布。


11.限制app支持的CPU架構的數目。刪除x86包下的so

在當前的Android生態系統中,讓app只支持armabi和x86架構就能夠了。
與第十條不同的是,x86包下的so在x86型號的手機是需要的,如果產品沒用這方面的要求也可以精簡。
建議實際工作的配置是隻保留armable、armable-x86下的so文件,算是一個折中的方案。


12.使用微信資源壓縮打包工具

微信資源壓縮打包工具通過短資源名稱,採用7zip對APP進行極致壓縮實現減小APP的目標,效果非常的好,強烈推薦。
詳情參考:Android資源混淆工具使用說明
原理介紹:安裝包立減1M–微信Android資源混淆打包工具
建議開啓7zip,注意白名單的配置,否則會導致有些資源找不到,官方已經發布AndResGuard到gradle中了,非常方便:

apply plugin: 'AndResGuard'
buildscript {
    dependencies {
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.1.7'
    }
}
andResGuard {
    mappingFile = null
    use7zip = true
    useSign = true
    keepRoot = false
    // add <your_application_id>.R.drawable.icon into whitelist.
    // because the launcher will get thgge icon with his name
    def packageName = <your_application_id>
    whiteList = [
        //for your icon
        packageName + ".R.drawable.icon",
        //for fabric
        packageName + ".R.string.com.crashlytics.*",
        //for umeng update
        packageName + ".R.string.umeng*",
        packageName + ".R.string.UM*",
        packageName + ".R.string.tb_*",
        packageName + ".R.layout.umeng*",
        packageName + ".R.layout.tb_*",
        packageName + ".R.drawable.umeng*",
        packageName + ".R.drawable.tb_*",
        packageName + ".R.anim.umeng*",
        packageName + ".R.color.umeng*",
        packageName + ".R.color.tb_*",
        packageName + ".R.style.*UM*",
        packageName + ".R.style.umeng*",
        packageName + ".R.id.umeng*"
    ]
    compressFilePattern = [
        "*.png",
        "*.jpg",
        "*.jpeg",
        "*.gif",
        "resources.arsc"
    ]
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.1.7'
        //path = "/usr/local/bin/7za"
    }
}

會生成一個andresguard/resguard的Task,自動讀取release簽名進行重新混淆打包。


13.使用provided編譯

對於一些庫是按照需要動態的加載,可能在某些版本並不需要,但是代碼又不方便去除否則會編譯不過。
使用provided可以保證代碼編譯通過,但是實際打包中並不引用此第三方庫,實現了控制APP大小的目標。
但是也同時就需要開發者自己判斷不引用這個第三方庫時就不要執行到相關的代碼,避免APP崩潰。


14.使用shape背景

特別是在扁平化盛行的當下,很多純色的漸變的圓角的圖片都可以用shape實現,代碼靈活可控,省去了大量的背景圖片。


15.使用着色方案

相信你的工程裏也有很多selector文件,也有很多相似的圖片只是顏色不同,通過着色方案我們能大大減輕這樣的工作量,減少這樣的文件。
藉助於android support庫可實現一個全版本兼容的着色方案,參考代碼:DrawableLess.java


16.在線化素材庫

如果你的APP支持素材庫(比如聊天表情庫)的話,考慮在線加載模式,因爲往往素材庫都有不小的體積。
這一步需要開發者實現在線加載,一方面增加代碼的複雜度,一方面提高了APP的流量消耗,建議酌情選擇


17.避免重複庫

避免重複庫看上去是理所當然的,但是祕密總是藏的很深,一定要當心你引用的第三方庫又引用了哪個第三方庫,這就很容易出現功能重複的庫了,比如使用了兩個圖片加載庫:Glide和Picasso。
通過查看exploded-aar目錄和External Libraries或者反編譯生成的APK,儘量避免重複庫的大小,減小APP大小。


18.使用更小的庫

同樣功能的庫在大小上是不同的,甚至會懸殊很大。
如果並無對某個庫特別需求而又對APP大小有嚴格要求的話,比較這些相同功能第三方庫的大小,選擇更小的庫會減小APP大小。


19.支持插件化

過去的一年,插件化技術雨後春筍一樣的都冒了出來,這些技術支持動態的加載代碼和動態的加載資源,把APP的一部分分離出來了,對於業務龐大的項目來說非常有用,極大的分解了APP大小。
因爲插件化技術需要一定的技術保障和服務端系統支持,有一定的風險,如無必要(比如一些小型項目,也沒什麼擴展業務)就不需要了,建議酌情選擇。


20.精簡功能業務

這條完全取決於業務需求。
從統計數據分析砍掉一些沒用的功能是完全有可能的,甚至乾脆去掉一些花哨的功能出個輕聊版、極速版也不是不可以的。


21.重複執行第1到20條

多次執行上述步驟,你總能發現一些蛛絲馬跡,這是一個好消息,不是嗎?


22 Facebook的redex優化字節碼

redex是facebook發佈的一款android字節碼的優化工具,需要按照說明文檔自行配置一下。

redex input.apk -o output.apk --sign -s <KEYSTORE> -a <KEYALIAS> -p <KEYPASS>

下面我們來看看它的效果,僅redex的話,減小了157k:

 

Paste_Image.png

先進行微信混淆,再進行 redex 。
據反應redex後會有崩潰的現象,這個要留意一下,我這裏壓縮之後都是可以正常運行的。

三、後續補充
如果不是非要用到v7包可以將v7包刪掉,可以小1兆


簡要評估

指南條例 適用範圍 易用性 風險指數 備註
使用一套資源 非極高UI要求的APP -
開啓minifyEnabled 全部 -
開啓shrinkResources 全部 -
刪除無用的語言資源 非全球國際化應用 -
使用tinypng有損壓縮 非極高UI要求的APP -
使用jpg格式 僅限非透明大圖 -
使用webp格式 僅限4.0+,4.2+設備 -
縮小大圖 限允許縮小的大圖 -
覆蓋第三庫裏的無用大圖 全部 -
刪除armable-v7包下的so 限允許對極少數設備不兼容 -
刪除x86包下的so 限允許對x86設備不兼容 -
使用微信資源壓縮打包工具 全部 切記要配置白名單
使使用provided編譯 全部 容錯處理
使用shape背景 全部 -
使用着色方案 全部 -
表情在線化 限含表情包的APP -
避免重複庫 全部 -
使用更小的庫 全部 -
支持插件化 限擴展性要求高的APP -
精簡功能業務 限允許精簡的APP -
Redex優化字節碼 全部 -


本文轉自:
作者:路國強
鏈接:https://www.jianshu.com/p/42e6a155f58e
來源:簡書
感謝作者。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章