性能優(yōu)化(6)-減小APK體積

主目錄見:Android高級進階知識(這是總目錄索引)
[譯]Reduce APK Size
?個人感覺這篇文章寫得還是比較全的钮热,所以這里就來翻譯一下這篇文章蚁飒,希望大家看了能有所收獲徽曲。這篇是谷歌自己的文章渣淤,應該來說還是比較權威的户誓,APK的體積變小意味著用戶下載時候需要的流量也比較少尚洽,而且下載時間相對縮短乎折,這是一個不錯的用戶體驗绒疗。

一.目標

今天翻譯這篇文章主要是為了大家了解有這么多可以縮小apk包體積的方法,在自己寫代碼的時候可以適當地注意骂澄,所以今天目標如下:
1.了解減小apk體積的若干方法吓蘑;
2.能在實際場景中考慮和使用到里面的方法。

二.譯文

?用戶通常會避免下載大應用坟冲,特別是市場上的設備連接到2G和3G或者按字節(jié)流量付費磨镶。這篇文章重點描述了怎么減少你應用Apk的體積,讓更多的用戶能下載它健提。

1.理解APK結構

?在討論怎么減小Apk體積之前琳猫,理解一個應用的APK結構是非常有幫助的。一個apk文件就是由一個zip壓縮包組成矩桂,這個zip包含了所有組成你應用的文件沸移。這些文件包含了java的字節(jié)碼文件,資源文件和一個包含了編譯后資源的文件侄榴。
?一個apk包含了如下的目錄:

  • META-INF/: 包含了CERT.SFCERT.RSA簽名文件雹锣,以及MANIFEST.MFmanifest 文件.
  • assets/:包含了應用的assets,應用可以通過 AssetManager對象來獲取這些資源.
  • res/:包含了沒有被編譯成resources.arsc的所有資源.
  • lib/:包含了用于軟件處理的編譯后的代碼癞蚕,這個目錄還包含了針對不同平臺類型的子目錄 armeabi, armeabi-v7a, arm64-v8a, x86, x86_64mips.

一個APK還包含了如下的文件蕊爵,但是其中只有AndroidManifest.xml是必須的。

  • resources.arsc:包含了編譯后的資源桦山。這個文件包含了res/values/文件夾下面的所有XML文件內容攒射,打包工具抽取了XML文件內容醋旦,并把它編譯成二進制文件格式,并且進行壓縮会放。該內容包含了language strings(語言相關的字符串)和styles饲齐,并且包括沒有直接放在resources.arsc文件中的內容路徑,比如layout文件以及圖片文件.
  • classes.dex:包含了class文件編譯成的dex文件咧最,這是可以被Dalvik/ART虛擬機識別的文件格式捂人。
  • AndroidManifest.xml:包含了Android核心manifest文件。這個文件羅列了應用的名字矢沿,版本滥搭,訪問權限和引用的library庫。該文件采用Android的二進制XML格式捣鲸。

2.減小資源數量和體積

?你apk的體積直接影響了你程序的加載速度瑟匆,占用內存大小,消耗的電量栽惶。一個簡單有效的方法是減小apk包含的資源的數量和體積愁溜。特別是,你可以移除一些不再使用的資源媒役,或者你可以使用一些可擴展的 Drawable對象來替代圖片資源祝谚。這部分主要討論這些方法以及另外可以減少資源占用的方法。

移除無用的資源

?使用Lint工具酣衷,這是一個Android Studio中的靜態(tài)代碼分析工具,可以檢測 res/文件夾中沒有被引用的資源(其實Lint工具不僅僅有這個功能)次泽。當Lint檢測到工程中潛在的不被使用的資源穿仪,它就會打印出如下消息:

res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources]

注意:Lint不會掃描assets/文件夾,assets資源是通過反射來引用的意荤,或者應用中引用的其他library庫啊片。他只是給你一個警告,并不會幫助你移除這些無用的資源玖像。

同時你添加到代碼中的library庫可能包含無用的資源紫谷,如果你在app里的build.gradle中啟用了shrinkResources,那么Gradle 會自動幫你移除這些無用的資源捐寥。

 android {
    // Other settings

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

為了使用shrinkResources笤昨,你必須開啟 code shrinking。在build階段握恳,ProGuard會移除無用的代碼但是會保留無用的資源瞒窒。然后Gradle過后會移除無用的資源。

更多的關于ProGuard 和使用Android Studio 幫助你減少Apk體積的方法乡洼,參閱Shrink Your Code and Resources.

在Android Gradle Plugin 0.7或者更高的版本崇裁,你可以聲明app支持的所有配置匕坯,Gradle會把resConfigresConfigsflavors 和defaultConfig等選項信息傳遞給構建系統(tǒng)。構建系統(tǒng)會防止一些不受支持的資源出現在你的apk中拔稳,從而減少你的apk體積葛峻。想要了解更多這方面的特性,參考Remove unused alternative resources巴比。

最小化Library庫中資源使用

?在開發(fā)android應用的時候泞歉,你經常會使用外部的library庫來提升你app的可用性和擴展性。例如匿辩,你會引入Android Support Library來提升用戶在舊機型上面的體驗腰耙,或者你會使用Google Play Services來自動翻譯你app中的文本。
?如果一個library庫被設計為一個服務或者桌面铲球,那么它就會包含很多你應用沒有用到的對象和方法挺庞。為了只包含你工程中用到的部分,你可以修改這個庫文件稼病,如果license許可的話选侨,同時你也可以使用另外的移動端友好的庫來給你的app增加特定的功能。
注意:然走,ProGuard能清除導入庫中一些無用的代碼援制,但是不能清除庫中大的內部依賴。

只支持特定的分辨率

?Android支持了非常多的不同分辨率的設備芍瑞,在Android 4.4 (API level 19)或者更高版本晨仑,框架支持了不同的分辨率:ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpixxxhdpi,雖然Android支持了這些所有的分辨率,但是你并不需要導出所有柵格化的assets到各個分辨率拆檬。
?如果你知道只有一小部分用戶使用特定分辨率的設備洪己,請考慮是否需要支持這些分辨率。如果你沒包含特定屏幕分辨率的資源竟贯,那么Android會自動縮放其他分辨率的資源來支持答捕。
?如果你的app只需要縮放的圖片,那么為了節(jié)省空間你可以使用單個版本在drawable-nodpi/中的圖片屑那,我們建議拱镐,每個應用都至少有一個xxhdpi版本的圖片。
想要更多關于屏幕分辨率的信息持际,請參照Screen Sizes and Densities

使用drawable對象

?一些圖片不需要一個靜態(tài)圖片資源:框架能在運行期動態(tài)繪制一張圖片沃琅,Drawable對象(<shape> in XML)只在你的apk中占用非常小的控件。另外选酗,XML Drawable對象能生成符合material design指南的單色圖阵难。

重用資源

?你可能會針對一張圖片的不同變形而提供單獨的資源,比如圖像的著色(tinted),陰影(shaded)或者旋轉(rotated)芒填。我們建議就算這樣呜叫,你可以重用這個資源空繁,在運行期時候根據需要進行自定義。
?Android提供了不同的工具來改變一個asset的顏色朱庆,比如在Android 5.0 (API level 21) 或者更高版本上面使用android:tinttintMode屬性 盛泡,在低版本平臺上則可以使用 ColorFilter類。
?你甚至可以忽略掉那些僅僅只是做了一個旋轉變化的資源娱颊,以下的代碼段就提供了一個以圖片中心點為圓心旋轉180度傲诵,將圖片從"朝上"變成"朝下"的例子。

<?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" />
從代碼中渲染

?同時你也可以在程序上渲染你的圖片以減少apk的體積箱硕,程序渲染將會釋放你的很多空間拴竹,因為你的程序中不會存儲一張圖片資源。

處理PNG文件

?在build階段剧罩,aapt工具能利用無損壓縮來優(yōu)化放在res/drawable/中的圖片資源栓拜。例如,aapt工具能利用顏色調色板(color palette)將不需要多于256種顏色的真彩色PNG轉化成一個八位PNG惠昔。這樣做會產生一個質量相同但是占用空間小的圖片幕与。
?但是要記住appt工具有如下的限制:

  • aapt工具不會壓縮包含在asset/中的PNG文件
  • 圖片文件需要256個或者更少的顏色來給aapt工具優(yōu)化
  • aapt工具可能會使已經壓縮過的PNG文件變大,為防止這種情況發(fā)生镇防,你可以在Gradle中使用cruncherEnabled 標識來禁用PNG文件的處理啦鸣。
aaptOptions {
    cruncherEnabled = false
}
壓縮PNG和JPEG文件

?你能使用工具來減少PNG圖片的體積但是不損失他的質量,例如: pngcrush,pngquant或者zopflipng.這些工具都可以減少PNG的體積但是不損失他的質量来氧。

pngcrush工具是非常高效地:這個工具會迭代所有的PNG文件過濾器和zlib (Deflate) 參數诫给。利用過濾器和參數的組合來壓縮一張圖片,然后他會選擇產生最小壓縮輸出的配置饲漾。

壓縮JPEG圖片你可以利用 packJPGguetzli.

使用WebP文件格式

?在Android 3.2 (API level 13)或者更高版本上面蝙搔,你同時可以使用WebP文件格式來替代你的PNG和JPEG文件。WebP格式提供了有損壓縮(如JPEG)和透明度(如PNG)考传,但是他能提供更好的壓縮比。

?你可以用Android Studio來將BMP证鸥,JPG僚楞,PNG 或者靜態(tài)GIF 圖片轉化為WebP格式,想要更多信息枉层,請參考Create WebP Images Using Android Studio

注意:Google Play只接受launcher icons為PNG格式的apk泉褐。

使用矢量圖片

?你可以使用矢量圖片來創(chuàng)建分辨率獨立的圖標或者其他可伸縮媒體。使用這些圖形可以大大減少你的apk體積鸟蜡,矢量圖片可以在 VectorDrawable展示膜赃,使用VectorDrawable對象可以用100字節(jié)的文件就產生一張屏幕大小的文件。

但是不足的是揉忘,他需要大量時間來渲染VectorDrawable對象跳座,如果圖片更大端铛,需要的時間可能會更多。所以在展示小圖片的時候我們可以考慮使用矢量圖片疲眷。

想要了解更多使用VectorDrawable對象的信息禾蚕,請看Working with Drawables

使用矢量圖來替換動畫圖片

?不用使用 AnimationDrawable來創(chuàng)建逐幀動畫,因為這么做需要你為每一幀動畫都包含一張bitmap圖片狂丝,這樣會大大增加你的apk體積换淆。

作為替代,你可以使用 AnimatedVectorDrawableCompat來創(chuàng)建 animated vector drawables

3.減少Native和java的代碼

這里有幾種減少你Native和java代碼庫的方法:

減少不必要的生成的代碼

?確保你能夠理解任何自動生成的代碼的部分几颜。例如倍试,一些protocol buffer工具能生成一些多余的方法和類,這無疑會是你的app體積變成兩倍三倍蛋哭。

避免使用枚舉

一個獨立的枚舉能增加1.0到1.4KB的大小到你的classes.dex文件县习,對于一些復雜系統(tǒng)或者共享庫可能增加的會更快。如果可能具壮,你可以使用@IntDef注解和ProGuard來去掉枚舉并將它們轉化為整型准颓。這種類型轉換保留了枚舉的所有類型安全的好處。

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

如果你的程序使用native代碼或者android NDK棺妓,那么你也可以優(yōu)化你的代碼來減少apk體積攘已,兩個有用的方式是刪除debug標記,不提取本地庫怜跑。

1.移除debug標記
如果你的應用在開發(fā)中并且需要調試样勃,那么讓你的debug 標記有意義。使用android NDK中提供的arm-eabi-strip工具來移除native庫中不需要的debug標記性芬。之后峡眶,再編譯你的release版本。

2.避免抽取native庫
.so文件未壓縮存儲于apk中植锉,然后在你app manifest中的<application>設置android:extractNativeLibs標記為false辫樱,這樣會防止 PackageManager在安裝過程中從apk中拷貝出來.so文件,而且還會帶來一個好處就是會使你的app差分更新變得更小俊庇。

保持多個精簡版apk

你的apk可能會包含有用戶下載了但是未使用到的內容狮暑,比如區(qū)域或者語言信息。為了給你用戶創(chuàng)建最小化的下載辉饱,你可以將你的app分出多個apk搬男,并且根據屏幕尺寸和GPU紋理支持等因素來細分。

當用戶下載你的應用的時候彭沼,他的設備就會根據設備特征和配置來獲取正確的apk缔逛。這樣,設備不會接收設備沒有的功能的資源。例如褐奴,用戶有hdpi的設備按脚,他們就不需要為更高分辨率設備準備的xxxhdpi資源。

想要更多信息的話歉糜,請參考 Configure APK SplitsMaintaining Multiple APKs

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末乘寒,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子匪补,更是在濱河造成了極大的恐慌伞辛,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夯缺,死亡現場離奇詭異蚤氏,居然都是意外死亡,警方通過查閱死者的電腦和手機踊兜,發(fā)現死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門竿滨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捏境,你說我怎么就攤上這事于游。” “怎么了垫言?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵贰剥,是天一觀的道長蜓氨。 經常有香客問我脆荷,道長,這世上最難降的妖魔是什么晌砾? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任凛捏,我火速辦了婚禮担忧,結果婚禮上,老公的妹妹穿的比我還像新娘坯癣。我一直安慰自己瓶盛,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布示罗。 她就那樣靜靜地躺著蓬网,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹉勒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天吵取,我揣著相機與錄音禽额,去河邊找鬼。 笑死,一個胖子當著我的面吹牛脯倒,可吹牛的內容都是我干的实辑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼藻丢,長吁一口氣:“原來是場噩夢啊……” “哼剪撬!你這毒婦竟也來了?” 一聲冷哼從身側響起悠反,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤残黑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后斋否,有當地人在樹林里發(fā)現了一具尸體梨水,經...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年茵臭,在試婚紗的時候發(fā)現自己被綠了疫诽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡旦委,死狀恐怖奇徒,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情缨硝,我是刑警寧澤摩钙,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站追葡,受9級特大地震影響腺律,放射性物質發(fā)生泄漏。R本人自食惡果不足惜宜肉,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一匀钧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谬返,春花似錦之斯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酿炸,卻和暖如春瘫絮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背填硕。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工麦萤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鹿鳖,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓壮莹,卻偏偏與公主長得像翅帜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子命满,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,755評論 25 707
  • 1涝滴、 前言 如果你對App優(yōu)化比較敏感,那么Apk安裝包的大小就一定不會忽視胶台。關于瘦身的原因歼疮,大概有以下幾個方面:...
    未來的理想閱讀 10,960評論 4 39
  • 是四月末,熬人的月份最后幾天概作,好在放假了腋妙,離開學校時一直膽戰(zhàn)心驚,說是下雨的天氣縱使再是晴讯榕,我也不敢昂首骤素。那晚的天...
    劉賦閱讀 240評論 0 0
  • 談一個三流大學的大學新生的生活,今天是十月二十八號一個月有這么不知不覺的過去了愚屁,說實話我覺得自己過得很稀爛济竹,為什...
    柒易先生閱讀 322評論 1 0