首發地址:http://www.jayfeng.com/2015/12/29/APK%E7%98%A6%E8%BA%AB%E5%AE%9E%E8%B7%B5/html
由於推廣的須要,公司須要把APK的大小再「減少」一下,4M之內!
當達到4M之內以後,公司建議說,可否再壓壓?2M如何?java
由於平時就考慮到大小的限制,因此不少工做已經作過了,以下列舉如今的狀態:android
- 7.3M(Debug版本)和6.5M(Release版本)
- 開啓minifyEnabled
- 開啓shrinkResources
- 已經去除不相關的大型庫
- 圖片和代碼已經經歷過粗略的一輪清理
...
android打包自己會對png進行無損壓縮,不信你們能夠看看apk中的圖片的大小實際上比你代碼工程裏的圖片要小(針對沒進行過無損壓縮的那些png圖)。
因此,純粹的進行無損壓縮並不會對apk的減少有任何效果,這是我特別想在這裏強調的一個經驗。
如今你們主流的比較喜歡用的tinypng實際上是有損壓縮:git
https://tinypng.com/
[原文] TinyPNG uses smart lossy compression techniques to reduce the file size of your PNG files...
[翻譯] TinyPNG使用智能有損壓縮技術,來減小PNG文件的大小...github
經過tinypng確實能在儘可能少的損失下再減少apk,若是圖片資源多或者大的話,效果仍是很明顯的。
具體減小多少,由於這個處理過程咱們是間隔作的,沒法準確給出結果,就按200k~500k算吧。web
經驗發現,一些背景,啓動頁,宣傳頁的PNG圖片比較大,這些圖片圖形比較複雜,若是轉用有損JPG可能只有不到一半(固然是有損,不過經過設置壓縮參數能夠這種損失比較小到忽略)。
由於都是大圖,因此這種方式能有效減少apk的大小。
這種狀況下的apk的減少是不可估量的。
json
若是png大圖轉成jpg仍是很大,或者想壓的更小,而儘可能不下降畫質,那麼能夠考慮一下webp。bash
android 4.0+才原生支持webp, 可是咱們的app是兼容2.3+,因此4.0如下的設備將沒法看到圖片。微信
咱們選擇不對4.0如下作webp兼容處理,不顯示就不顯示。不然,要引入webp相關so文件增大apk大小。網絡
經過把下面四張大圖換成webp,webp的quality參數按50配置(聽說官方評測75是最佳值),清晰度勉強能夠接受,這個值你們具體按產品要求來定。
其中安裝jpg轉webp工具:
brew install webp
轉換命令以下
cwebp -q <quality> input.jpg -o output.webp // Example: cwebp -q 50 a.jpg -o a.webp
更多下載:https://developers.google.com/speed/webp/docs/precompiled
最終,apk減少了188k。
補充:
在4.0 ~ 4.2.1的設備上沒法顯示帶有透明度的webp,好比,把png轉成webp則沒法顯示,可是若是把png先轉成jpg再轉成webp則能正常顯示了,但會丟失透明度。參考連接:http://developer.android.com/guide/appendix/media-formats.html
若是通過上面的步驟,依然存在大圖的話,說明確實圖有點大了,可能真的有點大了!
因此,要考慮的問題是,是否有必要保證如此的大小?可否縮小?
若是這方面能減少的話,apk瘦身的效果必然又會上一個檔次。
這種狀況下的apk的減少是不可估量的。
一些aar庫裏面包含根本就沒有用的圖。最典型的是support-v4兼容庫中包含一些「可能」用到的圖片,實際上在你的app中不會用到。
我沒有把全部圖都替換掉,只是把幾張大一點點的圖(選中的那些圖)用1x1的圖片替換,若是9patch圖的話,要作成3x3的9patch圖替換。
support庫可能還算好的,就怕有些庫引用了一些大圖而不自知,能夠在
apk減少了18k。
感謝@楊輝__ ,@kymjs張濤的提醒,armable-v7和armable文件夾能夠只保留armable。
固然,armable-v7a的庫會對圖形渲染方面有很大的改進,由於咱們主要是一些業務上動態庫,因此刪掉無大礙。
apk減少了191k。
這個方案網上一直在說,以前一直沒有需求或者動力實踐,在這裏感謝一下@裸奔的凱子哥的推薦和交流,他那邊的apk能夠壓小1M,效果仍是比較驚人的。
這個步驟我是在後面不少步壓縮以後測試的,每一個階段的壓縮結果都會有些許出入,因此數據僅供參考。
經過正常壓縮,apk包減少了464k。
若是開啓7zip,apk包減少了594k。
apk減少了594k。
PS: 關於這個壓縮,我集成到了gradle腳本中了,新建了一個Task,大概代碼以下:
task compressReleaseApp { // 在現有release的版本上生成到compressed目錄下 def appid = "appid" def channel = "abcdefghijkl" def guardJarFile = file('../AndResGuard/andresguard-1.1.jar') def guardConfigFile = file('../AndResGuard/config.xml') def originApkFile = file("../app.${appid}/build/outputs/apk/release/${appid}-release-${rootProject.ext.versionName}-${rootProject.ext.versionCode}-${channel}.apk") def outputDir = file("../app.${appid}/build/outputs/apk/compressed/") def keystoreFile = file(RELEASE_STORE_FILE) // 開始執行壓縮命令 def proc = "java -jar ${guardJarFile} ${originApkFile} -config ${guardConfigFile} -out ${outputDir} -signature ${keystoreFile} ${RELEASE_STORE_PASSWORD} ${RELEASE_KEY_PASSWORD} ${RELEASE_KEY_ALIAS}".execute(); proc.waitFor(); println "return code: ${ proc.exitValue()}" + ", stderr: ${proc.err.text}" + " stdout: ${proc.in.text}" }
config開啓了7zip, 部分配置以下:
<?xml version="1.0" encoding="UTF-8"?> <resproguard> <!--defaut property to set --> <issue id="property" > <seventzip value= "true" /> <!-- ... --> </issue> <issue id="whitelist" isactive="true"> <path value ="com.xxx.yyy.R.drawable.emoji_*" /> <path value ="com.xxx.yyy.... /> </issue> <issue id ="compress" isactive="true"> <!-- ... --> </issue> </resproguard>
詳情參考:Android資源混淆工具使用說明
原理介紹:安裝包立減1M--微信Android資源混淆打包工具
以前爲了簡單起見,不少包都直接忽略了,如今啓動嚴格模式,把能混淆的都混淆了:
採用微信壓縮方案最終效果比較:
apk減少了215k。
PS:混淆後,必定要通過嚴格測試,有時候甚至很難發現錯誤,好比我開啓嚴格混淆,用了一段時間以後慢慢發現了兩個bug,排除了兩個包程序才正常。
有意思的是,不管什麼時候何地去清理代碼和資源,總能有新的發現:
- 新發現或者新引入的無用圖片
- 這幾張圖怎麼同樣
- 這個類好像沒有用
- 沒用的類相關的圖片也沒用
- 有些圖片能夠用着色方案替換
- 有些圖片能夠用shape來代替
- hdpi裏的ic_luancher.png好像也能夠刪掉
- ...
apk減少了66k。
以前爲了保留調試信息,咱們是在Proguard保留了符號表的:
-keepattributes SourceFile,LineNumberTable
官方渠道我以爲仍是儘可能保留這個,如今針對推廣渠道,只能採用特殊手段,註釋這一行。
apk減少了230k。
ps:之後友盟上看推廣渠道的bug要辛苦一點,手動上傳mapping.txt了。
能夠對僅在運行時須要的庫設置provided關鍵字,實際並不被打包:
provided 'com.android.support:support-annotations:22.0.0'
我沒有發現這樣的場景,若是說有的話,就是support-annotations,可是通過後來的測試驗證,support-annotations原本就會在release版本中被minifyEnabled掉,因此對support-annotations設置provided是沒有意義的。
若是有實際場景,歡迎留言說明,不甚感激。
apk沒有減少。
雖然應用的表情很少,只有50來個,可是若是能把這部分表情放到網上,不只能有效減少apk大小,還能夠方便後期擴展支持:
打包成emoji_v1.zip, 大小是202k。
如今把emoji_v1.zip放到網上,按需下載後使用,最終對比結果以下:
apk減少了193k。
考慮着色方案主要目的是更方便支持多主題,減輕UI工做量,減小工程裏一大堆selector文件等,而後纔是,順便的減少一下apk大小。
經過着色方案,咱們去除了10多張純色的按下狀態圖片和對應的xml等等。
apk減少了15k。
PS: 具體實現能夠參考 http://www.race604.com/tint-drawable/ ,而我也把它集成到了個人LessCode庫中了:DrawableLess.java
發現兩個地方:
- 如今發現七牛的SDK引用了android-async-http-1.4.6.jar,雖然不大,只有95.4k,可是感受徹底能夠寫一個輕量級的jar,控制在10~20k就足夠了,具體能夠在現有的網絡庫上實現。
- 本身工程使用的是UIL,可是引入的第三方庫引用了picasso,兩個重複的圖片下載庫也是徹底沒用必要的。
如今尚未處理這塊,新任務介入,延期優化,敬請期待。
這是一個很基本的點,可是確很容易被人忽視,當你仔細回顧的時候,有一些雞肋的功能或者庫,是幾無用處的。不如干脆去掉。
好比,在很早的時候,我就把咱們app裏的sharesdk刪除了,由於對於咱們的產品定位和推廣來看,這毫無心義。
這種狀況下的apk的減少是不可估量的。
這個視具體狀況決定。
由於咱們的APP裏面包含友盟和百度兩套統計系統,早期老闆要求,事實上後面已經不多看這方面的數據,百度統計的數據幾乎沒用人去看,能夠暫時先去除。
本來的百度統計的jar有130多k,去除以後的apk的減少會遠遠沒有這麼多。
apk減少了20k。
使用更小的庫不該該成爲你選擇方案的決定性因素,可是能夠做爲參考因素(freso確實太大了,這個大小也能夠成爲決定性因素)。
圖片下載,網絡請求,json解析等等的庫和它的競品都有多大,你內心有數嗎?
以工具庫爲例,網上有不少工具庫,可是每每它們的大小很難控制。
- xutils-3.2.6.aar -- 843.8k
- lite-common-1.1.3.jar -- 148.1k
- lesscode-core-0.8.2.aar -- 64k
- ...
上面最後一個庫LessCode是我本身收集的工具類集合,很是小:LessCode,混淆後只有不到50k大小。
不只提升了開發效率,減小了冗餘代碼,並且能避免引用一些其餘大型的庫,有效避免包的增大。
好比,咱們碰到過這樣的一個bug,快速點擊按鈕屢次觸發跳轉,如今RxJava結合RxBind有這樣的一個場景解決方案,若是引入這些庫的話必然會增大apk大小,實際上就幾行代碼,我把這樣的解決方案集成到了LessCode,下次別的項目碰到這樣的問題不用再猶豫是否要引入一個這麼大的庫了。
這些小的工具庫,建議根據本身的經驗人手總結一個,不求全,但求精!
這種狀況下的apk的減少是不可估量的。
尷尬的是,咱們所呈現的功能大部分都是重要的不可分割的功能,很難從業務上分離出來。
今年預計要實踐一個輕量級的插件化方案,用別人的也好,本身寫也好,但願能解決或者優化一些安裝包加載多模塊,或者主題切換,或者熱修復的問題。
這裏做爲候選方案備用。
這種狀況下的apk的減少是不可估量的。
一開始考慮瘦身,領導是容許適當的砍掉一些功能,由於4M的目標咱們已經實現了,因此如今尚未到砍功能的地步。
這裏做爲候選方案備用。
這種狀況下的apk的減少是不可估量的。
文章發出後,收到了一些朋友的建議,補充幾點。
感謝@牧志軒的建議,經過配置resConfigs能夠選擇只打包哪幾種語言,進而去掉各類aar包中全世界的語言,尤爲是support包中的。
選擇保留什麼語言要根據產品的用戶和市場來定,若是隻選擇默認英語和中文語言,配置以下
android { defaultConfig { resConfigs "zh" } }
看看效果:
若是不採用微信壓縮方案結果對比,apk減少了197k。
若是採用微信壓縮(開啓7zip)對比結果,apk只減少了16k,由於微信對resources.arsc進行了強力壓縮,厲害!
apk減少了16k。
再次感謝@楊輝__的建議,x86的包刪除了以後,測試反應好像有些機器容易崩潰,未能通過嚴格測試,因此主版本又復原了,只在個別渠道執行這條措施。
通常狀況下不會有問題,測試了一下效果,apk減少了78k。
這裏做爲候選方案備用。
最終,咱們成功的把apk壓到了2.9M,若是把上面遺漏的步驟繼續再作,應該還能再減少一點。 客戶反應壓的好小,領導簡直不敢相信~ 瘦身不難,難的是魔鬼瘦身!