從APK的文件結(jié)構(gòu)說起
APK在安裝和更新之前都需要經(jīng)過網(wǎng)絡(luò)將其下載到手機(jī)废士,如果APK越大消耗的流量就會越多灶搜,特別是對于使用移動網(wǎng)絡(luò)的用戶來講沧侥,消耗流量越多就代表需要花更多的錢去購買流量善玫。同時(shí)一些第三方應(yīng)用商城也會對上傳的APK大小有限制水援,所以為了能夠讓產(chǎn)品能夠更受商城和用戶歡迎密强,APK瘦身是第一步,更小的APK標(biāo)示著更多地用戶愿意去下載和體驗(yàn)蜗元。
為了能夠減小APK的大小或渤,首先需要知道APK由哪些部分構(gòu)成,然后針對每個(gè)部分做相應(yīng)的優(yōu)化工作奕扣,下圖是一個(gè)APK解壓后的文件結(jié)構(gòu):
![圖一:APK結(jié)構(gòu)](http://ww4.sinaimg.cn/large/6d17e381gw1eqvmdlfzdoj20s206y76z.jpg)
各文件的介紹如下:
classes.dex:classes.dex是java源碼編譯后生成的java字節(jié)碼文件薪鹦。但由于Android使用的dalvik虛擬機(jī)與標(biāo)準(zhǔn)的java虛擬機(jī)是不兼容的,dex文件與class文件相比惯豆,不論是文件結(jié)構(gòu)還是opcode都不一樣池磁。目前常見的java反編譯工具都不能處理dex文件。Android模擬器中提供了一個(gè)dex文件的反編譯工具楷兽,dexdump地熄。用法為首先啟動Android模擬器,把要查看的dex文件用adb push上傳的模擬器中芯杀,然后通過adb shell登錄端考,找到要查看的dex文件,執(zhí)行dexdump xxx.dex揭厚。另跛梗,有人介紹到Dedexer是目前在網(wǎng)上能找到的唯一一個(gè)反編譯dex文件的開源工具,需要自己編譯源代碼棋弥。
resources.arsc:編譯后的二進(jìn)制資源文件
AndroidManifest.xml:該文件是每個(gè)應(yīng)用都必須定義和包含的核偿,它描述了應(yīng)用的名字、版本顽染、權(quán)限漾岳、引用的庫文件等等信息,如要把a(bǔ)pk上傳到Google Market上粉寞,也要對這個(gè)xml做一些配置尼荆。在apk中的AndroidManifest.xml是經(jīng)過壓縮的,可以通過AXMLPrinter2工具解開唧垦,具體命令為:java -jar AXMLPrinter2.jar AndroidManifest.xml
proguard.cfg:代碼混淆配置文件捅儒;
project.properties:標(biāo)示APK的target sdk和依賴關(guān)系,這里的依賴關(guān)系指示的是該APK依賴到了哪些工程振亮;
assets:assets目錄可以存放一些配置文件(比如webview本地資源巧还、圖片資源等等),這些文件的內(nèi)容在程序運(yùn)行過程中可以通過相關(guān)的API獲得坊秸。具體的方法可以參考SDK中的例子:在sdk的 \SDK\1.6\android-sdk-windows-1.6_r1\platforms\android-1.6\samples\ApiDemos 例子中麸祷,有個(gè)com.example..android.apis.content 的例子,在這個(gè)例子中他把一個(gè)text文件放到工程的asset目錄下褒搔,然后把這個(gè)txt當(dāng)作普通文件處理阶牍。處理的過程在ReadAsset.java中喷面。同理枉疼,asset也可以放置其他文件存炮。
lib:lib目錄下的子目錄armeabi存放的是一些so文件放棒。這個(gè)地方多講幾句矛物,都是在開發(fā)過程中摸索出來的。eclipse在打包的時(shí)候會根據(jù)文件名的命名規(guī)則(lib****.so)去打包so文件蓉冈,開頭和結(jié)尾必須分別為“l(fā)ib”和“.so”烘浦,否則是不會打包到apk文件中的疚脐。其他非eclipse開發(fā)環(huán)境沒有測試過生宛。如果你是用SDK和NDK開發(fā)的話,這部分很重要肮柜,甚至可以通過把一些不是so文件的文件通過改名打包到apk中陷舅,具體能干些什么那就看你想干什么了,呵呵呵审洞!
META-INF:META-INF目錄下存放的是簽名信息莱睁,用來保證apk包的完整性和系統(tǒng)的安全。在eclipse編譯生成一個(gè)apk包時(shí)芒澜,會對所有要打包的文件做一個(gè)校驗(yàn)計(jì)算仰剿,并把計(jì)算結(jié)果放在META-INF目錄下。這就保證了apk包里的文件不能被隨意替換痴晦。比如拿到一個(gè)apk包后南吮,如果想要替換里面的一幅圖片,一段代碼誊酌, 或一段版權(quán)信息部凑,想直接解壓縮、替換再重新打包碧浊,基本是不可能的涂邀。如此一來就給病毒感染和惡意修改增加了難度,有助于保護(hù)系統(tǒng)的安全箱锐。
res:res目錄存放資源文件比勉。包括圖片、字符串驹止、raw文件夾下面的音頻文件浩聋、各種xml文件等等。
從圖一可知臊恋,APK中classes.dex赡勘、lib、資源文件是大頭捞镰,APK瘦身主要就是優(yōu)化這三類闸与,關(guān)于這三種類型的文件比較成熟的優(yōu)化方法有:
classes.dex:通過代碼混淆毙替,刪掉不必要的jar包和代碼實(shí)現(xiàn)該文件的優(yōu)化;
lib:一個(gè)硬件設(shè)備對應(yīng)一個(gè)架構(gòu)(mips践樱、arm或者x86)厂画,只保留與設(shè)備架構(gòu)相關(guān)的庫文件夾(主流的架構(gòu)都是arm的,mips屬于小眾拷邢,默認(rèn)也是支持arm的so的袱院,但x86的不支持),這樣可以大大降低lib文件夾的大胁t稼『雎澹?/p>
資源文件:通過Lint工具掃描代碼中沒有使用到的靜態(tài)資源。
上面介紹的三種類型文件的優(yōu)化方案的確能夠在一定程度上減小APK的大小环肘,但在最近做項(xiàng)目的過程中經(jīng)過研究發(fā)現(xiàn)還可以更進(jìn)一步優(yōu)化APK的大小欲虚,具體方案如下:
多分辨率適配:我之前寫過一篇關(guān)于多分辨率適配的文章Android多分辨率適配經(jīng)驗(yàn)總結(jié),一套圖、一套布局悔雹,多套dimens.xml文件复哆,在使用最小資源的情況下搞定多分辨率適配;
預(yù)置數(shù)據(jù):和游戲一樣腌零,程序和數(shù)據(jù)分離梯找,進(jìn)入模塊時(shí)下載預(yù)置數(shù)據(jù)(下載的策略需要注重用戶體驗(yàn),在需要使用數(shù)據(jù)的地方下載)益涧;
圖片資源:使用tinypng和webP锈锤,下面詳細(xì)介紹圖片資源優(yōu)化的方案。
圖片資源優(yōu)化攻略
圖片資源的優(yōu)化原則是:在不降低圖片效果闲询、保證APK顯示效果的前提下縮小圖片文件的大小牙咏。
使用tinypng優(yōu)化大部分圖片資源:
tinypng是一個(gè)支持壓縮png和jpg圖片格式的網(wǎng)站,通過其獨(dú)特的算法(通過一種叫“量化”的技術(shù)嘹裂,把原本png文件的24位真彩色壓縮為8位的索引演示妄壶,是一種矢量壓縮方法,把顏色值用數(shù)值123等代替寄狼。)可以實(shí)現(xiàn)在無損壓縮的情況下圖片文件大小縮小到原來的30%-50%丁寄。壓縮率和壓縮后的效果如下:
![圖二:tinypng圖片壓縮率展示](http://ww3.sinaimg.cn/large/6d17e381gw1eqvon5eozaj20qg0iqag0.jpg)
![圖上:tinpng圖片壓縮前后效果對比](http://ww4.sinaimg.cn/large/6d17e381gw1eqvotohjgaj20pk0inq49.jpg)
上面的圖片對比舉例不太好,不過可以看到壓縮前后圖片效果并沒有變化泊愧,需要說明的是:tinypng支持png和jpg圖片的壓縮伊磺,并且也支持9圖的壓縮。
tinypng的缺點(diǎn)是在壓縮某些帶有過渡效果(帶alpha值)的圖片時(shí)删咱,圖片會失真屑埋,這種圖片可以將png圖片轉(zhuǎn)換為下面介紹的webP格式,可以在保證圖片質(zhì)量的前提下大幅縮小圖片的大小痰滋。
tinypng提供了開放接口供開發(fā)者開發(fā)屬于自己的壓縮工具摘能,不過這是付費(fèi)服務(wù)续崖,對于普通用戶來說,tinypng為每個(gè)用戶提供的每月圖片免費(fèi)壓縮數(shù)量已經(jīng)足夠了团搞。
使用webP圖片格式:
WebP是谷歌研發(fā)出來的一種圖片數(shù)據(jù)格式严望,它是一種支持有損壓縮和無損壓縮的圖片文件格式,派生自圖像編碼格式 VP8逻恐。根據(jù) Google 的測試像吻,無損壓縮后的 WebP 比 PNG 文件少了 45% 的文件大小,即使這些 PNG 文件經(jīng)過其他壓縮工具壓縮之后复隆,WebP 還是可以減少 28% 的文件大小拨匆。目前很多公司已經(jīng)將webP技術(shù)運(yùn)用到Android APP中,比如FaceBook挽拂、騰訊惭每、淘寶。webP相比于png最明顯的問題是加載稍慢轻局,不過現(xiàn)在的智能設(shè)備硬件配置越來越高,這都不是事兒样刷。
假如你打算在 App 中使用 WebP仑扑,除了 Android4.0 以上提供的原生支持外,其他版本以可以使用官方提供的解析庫webp-android-backport編譯成so使用置鼻。
通常UI提供的圖片都是png或者jpg格式镇饮,我們可以通過智圖或者isparta將其它格式的圖片轉(zhuǎn)換成webP格式,isparta可實(shí)現(xiàn)批量轉(zhuǎn)換箕母,墻裂推薦储藐!
使用tintcolor實(shí)現(xiàn)按鈕反選效果:
通常按鈕的正反旋圖片我們都是通過提供一張按鈕正常圖片和一張按鈕反選圖片,然后通過selector實(shí)現(xiàn)嘶是,兩張圖片除了alpha值不一樣外其它的內(nèi)容都是重復(fù)的钙勃,在Android 5.0及以上的版本可以通過tintcolor實(shí)現(xiàn)只提供一張按鈕的圖片,在程序中實(shí)現(xiàn)按鈕反選效果聂喇,前提是圖片的內(nèi)容一樣辖源,只是正反選按鈕的顏色不一樣。
參考資料
本文重點(diǎn)講述圖片資源的優(yōu)化希太,關(guān)于APK瘦身可以從多個(gè)方面入手克饶,下面是一些關(guān)于APK瘦身值得閱讀的文章,本文也作了一些參考誊辉。只要用心專研矾湃,APK的大小肯定會控制下來的。