APK瘦身值得分享的一些經驗

現在apk越來越大,原因有如下幾個:

  APK在安裝和更新之前都需要經過網絡將其下載到手機,如果APK越大消耗的流量就會越多,特別是對於使用移動網絡的用戶來講,消耗流量越多就代表需要花更多的錢去購買流量。同時一些第三方應用商城也會對上傳的APK大小有限制,所以爲了能夠讓產品能夠更受商城和用戶歡迎,APK瘦身是第一步,更小的APK標示着更多地用戶願意去下載和體驗。

  爲了能夠減小APK的大小,首先需要知道APK由哪些部分構成,然後針對每個部分做相應的優化工作,下圖是一個APK解壓後的文件結構:

圖一:APK結構

  各文件的介紹如下:

  • classes.dex:classes.dex是java源碼編譯後生成的java字節碼文件。但由於Android使用的dalvik虛擬機與標準的java虛擬機是不兼容的,dex文件與class文件相比,不論是文件結構還是opcode都不一樣。目前常見的java反編譯工具都不能處理dex文件。Android模擬器中提供了一個dex文件的反編譯工具,dexdump。用法爲首先啓動Android模擬器,把要查看的dex文件用adb push上傳的模擬器中,然後通過adb shell登錄,找到要查看的dex文件,執行dexdump xxx.dex。另,有人介紹到Dedexer是目前在網上能找到的唯一一個反編譯dex文件的開源工具,需要自己編譯源代碼。

  • resources.arsc:編譯後的二進制資源文件

  • AndroidManifest.xml:該文件是每個應用都必須定義和包含的,它描述了應用的名字、版本、權限、引用的庫文件等等信息,如要把apk上傳到Google Market上,也要對這個xml做一些配置。在apk中的AndroidManifest.xml是經過壓縮的,可以通過AXMLPrinter2工具解開,具體命令爲:java -jar AXMLPrinter2.jar AndroidManifest.xml

  • proguard.cfg:代碼混淆配置文件;

  • project.properties:標示APK的target sdk和依賴關係,這裏的依賴關係指示的是該APK依賴到了哪些工程;

  • assets:assets目錄可以存放一些配置文件(比如webview本地資源、圖片資源等等),這些文件的內容在程序運行過程中可以通過相關的API獲得。具體的方法可以參考SDK中的例子:在sdk的 \SDK\1.6\android-sdk-windows-1.6_r1\platforms\android-1.6\samples\ApiDemos 例子中,有個com.example..android.apis.content 的例子,在這個例子中他把一個text文件放到工程的asset目錄下,然後把這個txt當作普通文件處理。處理的過程在ReadAsset.java中。同理,asset也可以放置其他文件。

  • lib:lib目錄下的子目錄armeabi存放的是一些so文件。這個地方多講幾句,都是在開發過程中摸索出來的。eclipse在打包的時候會根據文件名的命名規則(lib**.so)去打包so文件,開頭和結尾必須分別爲“lib”和“.so”,否則是不會打包到apk文件中的。其他非eclipse開發環境沒有測試過。如果你是用SDK和NDK開發的話,這部分很重要,甚至可以通過把一些不是so文件的文件通過改名打包到apk中,具體能幹些什麼那就看你想幹什麼了,呵呵呵!

  • META-INF:META-INF目錄下存放的是簽名信息,用來保證apk包的完整性和系統的安全。在eclipse編譯生成一個apk包時,會對所有要打包的文件做一個校驗計算,並把計算結果放在META-INF目錄下。這就保證了apk包裏的文件不能被隨意替換。比如拿到一個apk包後,如果想要替換裏面的一幅圖片,一段代碼, 或一段版權信息,想直接解壓縮、替換再重新打包,基本是不可能的。如此一來就給病毒感染和惡意修改增加了難度,有助於保護系統的安全。

  • res:res目錄存放資源文件。包括圖片、字符串、raw文件夾下面的音頻文件、各種xml文件等等。

  從圖一可知,APK中classes.dex、lib、資源文件是大頭,APK瘦身主要就是優化這三類,關於這三種類型的文件比較成熟的優化方法有:

  • classes.dex:通過代碼混淆,刪掉不必要的jar包和代碼實現該文件的優化;

  • lib:一個硬件設備對應一個架構(mips、arm或者x86),只保留與設備架構相關的庫文件夾(主流的架構都是arm的,mips屬於小衆,默認也是支持arm的so的,但x86的不支持),這樣可以大大降低lib文件夾的大小;

  • 資源文件:通過Lint工具掃描代碼中沒有使用到的靜態資源。

  上面介紹的三種類型文件的優化方案的確能夠在一定程度上減小APK的大小,但在最近做項目的過程中經過研究發現還可以更進一步優化APK的大小,具體方案如下:

  • 多分辨率適配:我之前寫過一篇關於多分辨率適配的文章Android多分辨率適配經驗總結,一套圖、一套佈局,多套dimens.xml文件,在使用最小資源的情況下搞定多分辨率適配;

  • 預置數據:和遊戲一樣,程序和數據分離,進入模塊時下載預置數據(下載的策略需要注重用戶體驗,在需要使用數據的地方下載);

  • 圖片資源:使用tinypng和webP,下面詳細介紹圖片資源優化的方案。

圖片資源優化攻略

  圖片資源的優化原則是:在不降低圖片效果、保證APK顯示效果的前提下縮小圖片文件的大小。

使用tinypng優化大部分圖片資源:

  tinypng是一個支持壓縮png和jpg圖片格式的網站,通過其獨特的算法(通過一種叫“量化”的技術,把原本png文件的24位真彩色壓縮爲8位的索引演示,是一種矢量壓縮方法,把顏色值用數值123等代替。)可以實現在無損壓縮的情況下圖片文件大小縮小到原來的30%-50%。壓縮率和壓縮後的效果如下:

圖二:tinypng圖片壓縮率展示

圖上:tinpng圖片壓縮前後效果對比

  上面的圖片對比舉例不太好,不過可以看到壓縮前後圖片效果並沒有變化,需要說明的是:tinypng支持png和jpg圖片的壓縮,並且也支持9圖的壓縮。

  tinypng的缺點是在壓縮某些帶有過渡效果(帶alpha值)的圖片時,圖片會失真,這種圖片可以將png圖片轉換爲下面介紹的webP格式,可以在保證圖片質量的前提下大幅縮小圖片的大小。

  tinypng提供了開放接口供開發者開發屬於自己的壓縮工具,不過這是付費服務,對於普通用戶來說,tinypng爲每個用戶提供的每月圖片免費壓縮數量已經足夠了。

使用webP圖片格式:

  WebP是谷歌研發出來的一種圖片數據格式,它是一種支持有損壓縮和無損壓縮的圖片文件格式,派生自圖像編碼格式 VP8。根據 Google 的測試,無損壓縮後的 WebP 比 PNG 文件少了 45% 的文件大小,即使這些 PNG 文件經過其他壓縮工具壓縮之後,WebP 還是可以減少 28% 的文件大小。目前很多公司已經將webP技術運用到Android APP中,比如FaceBook、騰訊、淘寶。webP相比於png最明顯的問題是加載稍慢,不過現在的智能設備硬件配置越來越高,這都不是事兒。

  假如你打算在 App 中使用 WebP,除了 Android4.0 以上提供的原生支持外,其他版本以可以使用官方提供的解析庫webp-android-backport編譯成so使用。

  通常UI提供的圖片都是png或者jpg格式,我們可以通過智圖或者isparta將其它格式的圖片轉換成webP格式,isparta可實現批量轉換,牆裂推薦!

使用tintcolor實現按鈕反選效果:

  通常按鈕的正反旋圖片我們都是通過提供一張按鈕正常圖片和一張按鈕反選圖片,然後通過selector實現,兩張圖片除了alpha值不一樣外其它的內容都是重複的,在Android 5.0及以上的版本可以通過tintcolor實現只提供一張按鈕的圖片,在程序中實現按鈕反選效果,前提是圖片的內容一樣,只是正反選按鈕的顏色不一樣。

參考資料

  本文重點講述圖片資源的優化,關於APK瘦身可以從多個方面入手,下面是一些關於APK瘦身值得閱讀的文章,本文也作了一些參考。只要用心專研,APK的大小肯定會控制下來的。


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