Android Gradle實用技巧(四) | 自動瘦身APK文件

Android Gradle必備使用技巧,未完待續(xù)缕贡,歡迎關注公眾號flysnow_org,第一時間看后續(xù)技巧。

隨著工程越來越大善绎,功能越來越多黔漂,開發(fā)人員越來越多,代碼越來越復雜禀酱,不可避免的會產生一些不在使用的資源,這類資源如果沒有清理的話牧嫉,會增加我們Apk的包大小剂跟,也會增加構建的時候。

要清理這些無用的資源酣藻,第一個辦法是我們在開發(fā)的過程中曹洽,把不再使用的資源清理掉,這個靠開發(fā)人員的自覺以及對程序代碼邏輯的了解成都辽剧,而且清理成本也比較大送淆。

第二個辦法是使用Android Lint,它會幫我們檢測出哪些資源沒有被使用怕轿,然后我們按照檢測出來的列表清理即可偷崩,這種辦法需要我們隔一段時間就要清理一次,不然就可能會有無用的資源遺留撞羽,做不到及時性阐斜。

以上兩個方式還有一個不能解決的問題,他就是第三方庫里的資源的問題诀紊。如果你引用的第三方庫里也含有無用的資源谒出,那么這兩種辦法都不能做到清理他們,因為他們被打包在第三方庫里邻奠,沒有辦法做刪除笤喳。

針對以上情況,Android Gradle為我們提供了在構建打包時自動清理掉未使用資源的方法碌宴,這個就是Resource Shrinking杀狡。他是一種在構建時,打包成Apk之前唧喉,會檢測所有資源捣卤,看看是否被引用,如果沒有八孝,那么這些資源就不會被打包到Apk包中.

因為是在這個過程中(構建時)董朝,Android Gradle構建系統(tǒng)會拿到所有的資源,不管是你項目自己的干跛,還是引用的第三方的子姜,它都一視同仁的處理,所以這個時機點可以控制哪些資源可以被打包,所以能解決第三方不使用的資源的問題哥捕。

比如我們常用的Google Play Service牧抽,這個是一個比較大的庫,它支持很多Google的服務遥赚,比如Google Drive扬舒,Google Sign In等等,如果你在你的應用中只使用了Google Drive這個服務凫佛,并沒有使用到Google Sign In服務讲坎,那么在構建打包的時候,會自動的處理Google Sign In功能相關的無用資源圖片愧薛。

Resource Shrinking要結合著Code Shrinking一起使用晨炕,什么是Code Shrinking呢?就是我們經常使用的ProGuard毫炉,也就是我們要啟用minifyEnabled瓮栗,是為了縮減代碼的;

我們上面已經講了瞄勾,自動清理未使用的資源的原理很簡單费奸,就是判斷有沒有用到這些資源,如果你的代碼還在使用丰榴,那么自然不會被清理货邓,所以要和代碼清理結合使用,先清理掉無用的代碼四濒,這樣這些無用的代碼引用的資源才能被清理掉换况。那么我們如何配置使用呢,看下面的示例盗蟆,如下Gradle配置來啟用Resource Shrinking:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

啟用Resource Shrinking是通過調用BuildType的shrinkResources來設置的戈二,只要給這個方法傳遞一個true的參數(shù),就可以啟用喳资,默認情況下是不啟用的觉吭。

/**
 * Whether shrinking of unused resources is enabled.
 *
 * Default is false;
 */
public void shrinkResources(boolean flag) {
    this.shrinkResources = flag;
}

當我們開啟了shrinkResources后,打包構建的時候仆邓,Android Gradle就會自動的處理未使用的資源鲜滩,不把他們打包到生成的Apk中,我們可以在我們構建輸出的日志中看到處理結果节值,以我們當前的示例代碼為例徙硅,我們運行./gradlew :app:assembleRelease 就可以看到如下日志:

:app:transformClassesWithDexForRelease
:app:transformClassesWithShrinkResForRelease
Removed unused resources: Binary resource data reduced from 159KB to 29KB: Removed 81%
Note: If necessary, you can disable resource shrinking by adding

從159KB減少到29KB,減少了81%搞疗,效果非常顯著嗓蘑,當然這是因為我演示的,現(xiàn)實中可能不會減少這么多,但是減少一點是一點桩皿。

以前是一個匯總的日志輸出豌汇,如果你想看詳細日志,想知道哪些資源被自動清理了泄隔,可以使用--info標記拒贱,顯示詳細的Gradle信息,然后把和自動清理資源的日志過濾出來即可佛嬉。我們可以通過如下命令實現(xiàn):

./gradlew clean :app:assembleRelease --info | grep "unused resource"

運行后我們可以通過日志輸出看到具體的哪些資源被清理了:

Skipped unused resource res/drawable/unused.jpg: 133399 bytes (replaced with small dummy file of size 0 bytes)
Removed unused resources: Binary resource data reduced from 159KB to 29KB: Removed 81%

自動清理未使用的資源這個功能雖好柜思,但是有時候會誤刪,為什么呢巷燥,因為我們在代碼編寫的時候可能會使用反射去引用資源文件,尤其很多你引用的第三方庫會這么做号枕,這時候Android Gradle就區(qū)分不出來了缰揪,可能會誤認為這些資源沒有被使用。針對這中情況葱淳,Android Gradle為我們提供了keep方法來讓我們配置哪些資源不被清理钝腺。

keep方法使用非常簡單,我們要新建一個xml文件來配置赞厕,這個文件是 res/raw/keep.xml艳狐,然后通過tools:keep屬性來配置,這個tools:keep接受一個以逗號(,)分割的配置資源列表皿桑,并且支持星號(*)通配符毫目。

有沒有覺得它和我們用ProGuard的配置文件是一樣的,我們在ProGuard配置文件里配置保存一些不被混淆的類也是這么做的诲侮。此外镀虐,對于res/raw/keep.xml這個文件我們不用擔心,Android Gradle構建系統(tǒng)最終打包的時候會清理它沟绪,不會把它打包進Apk中的刮便,除非你在代碼中通過R.raw.keep引用了它。

以下是res/raw/keep.xml示例绽慈,引用自Android Tech Docs

<?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*"/>

keep.xml還有一個屬性是 tools:shrinkMode恨旱,用于配置自動清理資源的模式,默認是safe坝疼,是安全的搜贤,這種情況下,Android Gradle可以識別代碼中類似于如下示例的引用

getResources().getIdentifier("unused","drawable",getPackageName());

這類代碼也被構建系統(tǒng)認為是使用了資源文件裙士,不會被清理入客。如果把清理模式改為strict,那么就沒有辦法識別了,這個資源會被認為沒有被引用桌硫,也會被清理掉夭咬。

除了shrinkResources之外,Android Gradle還為我們 提供了一個resConfigs铆隘,它屬于ProductFlavor的一個方法卓舵,可以讓我們配置哪些類型的資源才被打包到Apk中,比如只有中文的膀钠,只有hdpi格式的圖片等等掏湾,這是非常重要的,比如我們引用的第三方庫肿嘲,特別是Support Library 和 Google Play Services這兩個主要的大庫融击,因為國際化的問題,他們都支持了幾十種語言雳窟,但是對于我們的App來說尊浪,我們并不需要這么多,比如我們只用中文的語言就可以了封救,其他的都不需要拇涤;比如我們支持hdpi格式的圖片就好了,其他的都不需要誉结,這時候我們就可以通過resConfigs方法來配置:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "org.flysnow.app"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName '1.0.0'
        resConfigs 'zh'
    }
}

這樣我們就只保留了zh資源鹅士,其他非zh資源都不會被打包到Apk文件中。

其實這個resConfig的配置有3中辦法惩坑,一般常用的是resConfigs這個方法掉盅,因為可以同時指定多個配置,你也可以使用resConfig(后面沒有s)來指定一個配置旭贬,它一次只能添加一個怔接,如果要添加多個,要么調用多次稀轨,要么使用resConfigs方法扼脐。我們看下他們的方法原型,了解他們的方法原理:

/**
 * Adds a resource configuration filter.
 *
 * <p>If a qualifier value is passed, then all other resources using a qualifier of the same type
 * but of different value will be ignored from the final packaging of the APK.
 *
 * <p>For instance, specifying 'hdpi', will ignore all resources using mdpi, xhdpi, etc...
 */
public void resConfig(@NonNull String config) {
    addResourceConfiguration(config);
}
  
/**
 * Adds several resource configuration filters.
 *
 * <p>If a qualifier value is passed, then all other resources using a qualifier of the same type
 * but of different value will be ignored from the final packaging of the APK.
 *
 * <p>For instance, specifying 'hdpi', will ignore all resources using mdpi, xhdpi, etc...
 */
public void resConfigs(@NonNull String... config) {
    addResourceConfigurations(config);
}
  
/**
 * Adds several resource configuration filters.
 *
 * <p>If a qualifier value is passed, then all other resources using a qualifier of the same type
 * but of different value will be ignored from the final packaging of the APK.
 *
 * <p>For instance, specifying 'hdpi', will ignore all resources using mdpi, xhdpi, etc...
 */
public void resConfigs(@NonNull Collection<String> config) {
    addResourceConfigurations(config);
}

resConfig的使用非常廣泛奋刽,它的參數(shù)就是我們在Android開發(fā)時的資源限定符瓦侮,不止于我們上面描述的語言和密度,還包括Api Level佣谐,分辨率等等肚吏,具體的可以參考Android Doc文檔。

以上自動清理資源只是在打包的時候狭魂,不打包到Apk中罚攀,實際上并沒有刪除我們工程中的資源党觅,如果我們在使用的時候發(fā)現(xiàn)有大量的無用資源被清理,那么我們自己最好還是把這些資源文件從我們的工程中刪除吧斋泄,這樣也好維護一些杯瞻。

Android Gradle必備使用技巧,未完待續(xù)炫掐,歡迎關注公眾號flysnow_org魁莉,第一時間看后續(xù)技巧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末募胃,一起剝皮案震驚了整個濱河市旗唁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌痹束,老刑警劉巖检疫,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異祷嘶,居然都是意外死亡电谣,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門抹蚀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人企垦,你說我怎么就攤上這事环壤。” “怎么了钞诡?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵郑现,是天一觀的道長。 經常有香客問我荧降,道長接箫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任朵诫,我火速辦了婚禮辛友,結果婚禮上,老公的妹妹穿的比我還像新娘剪返。我一直安慰自己废累,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布脱盲。 她就那樣靜靜地躺著邑滨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钱反。 梳的紋絲不亂的頭發(fā)上掖看,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天匣距,我揣著相機與錄音,去河邊找鬼哎壳。 笑死毅待,一個胖子當著我的面吹牛,可吹牛的內容都是我干的耳峦。 我是一名探鬼主播恩静,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蹲坷!你這毒婦竟也來了驶乾?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤循签,失蹤者是張志新(化名)和其女友劉穎级乐,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體县匠,經...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡风科,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了乞旦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贼穆。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兰粉,靈堂內的尸體忽然破棺而出故痊,到底是詐尸還是另有隱情,我是刑警寧澤玖姑,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布愕秫,位于F島的核電站,受9級特大地震影響焰络,放射性物質發(fā)生泄漏戴甩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一闪彼、第九天 我趴在偏房一處隱蔽的房頂上張望甜孤。 院中可真熱鬧,春花似錦畏腕、人聲如沸课蔬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽二跋。三九已至,卻和暖如春流昏,著一層夾襖步出監(jiān)牢的瞬間扎即,已是汗流浹背吞获。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谚鄙,地道東北人各拷。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像闷营,于是被迫代替她去往敵國和親烤黍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,130評論 25 707
  • 這一章主要針對項目中可以用到的一些實用功能來介紹Android Gradle傻盟,比如如何隱藏我們的證書文件速蕊,降低風險...
    acc8226閱讀 7,616評論 3 25
  • 最近幾周一直在研究如何為APK瘦身,折騰了很久娘赴,是時候寫篇博客總結一下了规哲,雖然已經準備了下周一要在客戶端周會分享用...
    風清袖一閱讀 1,054評論 1 10
  • 前言 為什么需要學Gradle? Gradle 是 Android 現(xiàn)在主流的編譯工具,雖然在Gradle 出現(xiàn)之...
    真笨笨魚閱讀 1,490評論 0 0
  • 每訴說一次袄简,傷口便健康一點;我們習慣包裹泛啸,練就許多剛強痘番,以為這樣傷就沒了…… 但是如同天氣會有陰天下雨,并不總是清...
    妮不再來閱讀 1,037評論 37 48