Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android性能優化系列之apk瘦身

Android性能優化系列之apk瘦身

編輯:關於Android編程

為什麼APK要瘦身。APK越大,在下載安裝過程中,他們耗費的流量會越多,安裝等待時間也會越長;對於產品本身,意味著下載轉化率會越低(因為競品中,用戶有更多機會選擇那個體驗最好,功能最多,性能最好,包最小的),所以apk的瘦身優化也很重要,本篇博客將講述apk瘦身的相關內容。

使用一套資源

對於絕大對數APP來說,只需要取一套設計圖就足夠了。鑒於現在分辨率的趨勢,建議取720p的資源,放到xhdpi目錄。
相對於多套資源,只使用720P的一套資源,在視覺上差別不大,很多大公司的產品也是如此,但卻能顯著的減少資源占用大小,順便也能減輕設計師的出圖工作量了。
注意,這裡不是說把不是xhdpi的目錄都刪除,而是強調保留一套設計資源就夠了。

開啟minifyEnabled混淆代碼

在gradle使用minifyEnabled進行Proguard混淆的配置,可大大減小APP大小:

android {
    buildTypes {
        release {
            minifyEnabled true
        }
    }
}

在proguard中,是否保留符號表對APP的大小是有顯著的影響的,可酌情不保留,但是建議盡量保留用於調試。

參數:

-include {filename}    從給定的文件中讀取配置參數   
-basedirectory {directoryname}    指定基礎目錄為以後相對的檔案名稱   
-injars {class_path}    指定要處理的應用程序jar,war,ear和目錄   
-outjars {class_path}    指定處理完後要輸出的jar,war,ear和目錄的名稱   
-libraryjars {classpath}    指定要處理的應用程序jar,war,ear和目錄所需要的程序庫文件   
-dontskipnonpubliclibraryclasses    指定不去忽略非公共的庫類。   
-dontskipnonpubliclibraryclassmembers    指定不去忽略包可見的庫類的成員。

保留選項

-keep {Modifier} {class_specification}    保護指定的類文件和類的成員   
-keepclassmembers {modifier} {class_specification}    保護指定類的成員,如果此類受到保護他們會保護的更好   
-keepclasseswithmembers {class_specification}    保護指定的類和類的成員,但條件是所有指定的類和類成員是要存在。   
-keepnames {class_specification}    保護指定的類和類的成員的名稱(如果他們不會壓縮步驟中刪除)   
-keepclassmembernames {class_specification}    保護指定的類的成員的名稱(如果他們不會壓縮步驟中刪除)   
-keepclasseswithmembernames {class_specification}    保護指定的類和類的成員的名稱,如果所有指定的類成員出席(在壓縮步驟之後)   
-printseeds {filename}    列出類和類的成員-keep選項的清單,標准輸出到給定的文件  

壓縮

-dontshrink    不壓縮輸入的類文件   
-printusage {filename}   
-whyareyoukeeping {class_specification}  

優化

-dontoptimize    不優化輸入的類文件   
-assumenosideeffects {class_specification}    優化時假設指定的方法,沒有任何副作用   
-allowaccessmodification    優化時允許訪問並修改有修飾符的類和類的成員  

混淆

-dontobfuscate    不混淆輸入的類文件   
-printmapping {filename}   
-applymapping {filename}    重用映射增加混淆   
-obfuscationdictionary {filename}    使用給定文件中的關鍵字作為要混淆方法的名稱   
-overloadaggressively    混淆時應用侵入式重載   
-useuniqueclassmembernames    確定統一的混淆類的成員名稱來增加混淆   
-flattenpackagehierarchy {package_name}    重新包裝所有重命名的包並放在給定的單一包中   
-repackageclass {package_name}    重新包裝所有重命名的類文件中放在給定的單一包中   
-dontusemixedcaseclassnames    混淆時不會產生形形色色的類名   
-keepattributes {attribute_name,...}    保護給定的可選屬性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.  
-renamesourcefileattribute {string}    設置源文件中給定的字符串常量  

開啟shrinkResources去除無用資源

在gradle使用shrinkResources去除無用資源,效果非常好。

android {
    buildTypes {
        release {
            shrinkResources true
        }
    }
}

刪除無用的語言資源

大部分應用其實並不需要支持幾十種語言的國際化支持。還好強大的gradle支持語言的配置,比如國內應用只支持中文:

android {
    defaultConfig {
        resConfigs "zh"
    }
}

使用tinypng有損壓縮

android打包本身會對png進行無損壓縮,所以使用像tinypng這樣的有損壓縮是有必要的。
重點是Tinypng使用智能有損壓縮技術,以盡量少的失真換來圖片大小的銳減,效果非常好,強烈推薦。
Tinypng的官方網站:http://tinypng.com/

使用jpg格式

如果對於非透明的大圖,jpg將會比png的大小有顯著的優勢,雖然不是絕對的,但是通常會減小到一半都不止。
在啟動頁,活動頁等之類的大圖展示區采用jpg將是非常明智的選擇。

使用webp格式

webp支持透明度,壓縮比比jpg更高但顯示效果卻不輸於jpg,官方評測quality參數等於75均衡最佳。
相對於jpg、png,webp作為一種新的圖片格式,限於android的支持情況暫時還沒用在手機端廣泛應用起來。從Android 4.0+開始原生支持,但是不支持包含透明度,直到Android 4.2.1+才支持顯示含透明度的webp,使用的時候要特別注意。
官方介紹:https://developers.google.com/speed/webp/docs/precompiled

縮小大圖

如果經過上述步驟之後,你的工程裡面還有一些大圖,考慮是否有必要維持這樣的大尺寸,是否能適當的縮小。
事實上,由於設計師出圖的原因,我們拿到的很多圖片完全可以適當的縮小而對視覺影響是極小的。

覆蓋第三庫裡的大圖

有些第三庫裡引用了一些大圖但是實際上並不會被我們用到,就可以考慮用1x1的透明圖片覆蓋。
你可能會有點不舒服,因為你的drawable下竟然包含了一些莫名其妙的名稱的1x1圖片…

刪除armable-v7包下的so

基本上armable的so也是兼容armable-v7的,armable-v7a的庫會對圖形渲染方面有很大的改進,如果沒有這方面的要求,可以精簡。
這裡不排除有極少數設備會Crash,可能和不同的so有一定的關系,請大家務必測試周全後再發布。

刪除x86包下的so

與第十條不同的是,x86包下的so在x86型號的手機是需要的,如果產品沒用這方面的要求也可以精簡。
建議實際工作的配置是只保留armable、armable-x86下的so文件,算是一個折中的方案。

使用微信資源壓縮打包工具

微信資源壓縮打包工具通過短資源名稱,采用7zip對APP進行極致壓縮實現減小APP的目標,效果非常的好,強烈推薦。

建議開啟7zip,注意白名單的配置,否則會導致有些資源找不到,官方已經發布AndResGuard到gradle中了,非常方便:

apply plugin: 'AndResGuard'
buildscript {
    dependencies {
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.1.7'
    }
}
andResGuard {
    mappingFile = null
    use7zip = true
    useSign = true
    keepRoot = false
    // add .R.drawable.icon into whitelist.
    // because the launcher will get thgge icon with his name
    def packageName = 
            whiteList = [
    //for your icon
    packageName + ".R.drawable.icon",
            //for fabric
            packageName + ".R.string.com.crashlytics.*",
            //for umeng update
            packageName + ".R.string.umeng*",
            packageName + ".R.string.UM*",
            packageName + ".R.string.tb_*",
            packageName + ".R.layout.umeng*",
            packageName + ".R.layout.tb_*",
            packageName + ".R.drawable.umeng*",
            packageName + ".R.drawable.tb_*",
            packageName + ".R.anim.umeng*",
            packageName + ".R.color.umeng*",
            packageName + ".R.color.tb_*",
            packageName + ".R.style.*UM*",
            packageName + ".R.style.umeng*",
            packageName + ".R.id.umeng*"
    ]
    compressFilePattern = [
    "*.png",
            "*.jpg",
            "*.jpeg",
            "*.gif",
            "resources.arsc"
    ]
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.1.7'
        //path = "/usr/local/bin/7za"
    }
}

會生成一個andresguard/resguard的Task,自動讀取release簽名進行重新混淆打包。

使用provided編譯

對於一些庫是按照需要動態的加載,可能在某些版本並不需要,但是代碼又不方便去除否則會編譯不過。
使用provided可以保證代碼編譯通過,但是實際打包中並不引用此第三方庫,實現了控制APP大小的目標。
但是也同時就需要開發者自己判斷不引用這個第三方庫時就不要執行到相關的代碼,避免APP崩潰。

使用shape背景

特別是在扁平化盛行的當下,很多純色的漸變的圓角的圖片都可以用shape實現,代碼靈活可控,省去了大量的背景圖片。

使用著色方案

相信你的工程裡也有很多selector文件,也有很多相似的圖片只是顏色不同,通過著色方案我們能大大減輕這樣的工作量,減少這樣的文件。
借助於android support庫可實現一個全版本兼容的著色方案,參考代碼:DrawableLess.java

在線化素材庫

如果你的APP支持素材庫(比如聊天表情庫)的話,考慮在線加載模式,因為往往素材庫都有不小的體積。
這一步需要開發者實現在線加載,一方面增加代碼的復雜度,一方面提高了APP的流量消耗,建議酌情選擇。

避免重復庫

避免重復庫看上去是理所當然的,但是秘密總是藏的很深,一定要當心你引用的第三方庫又引用了哪個第三方庫,這就很容易出現功能重復的庫了,比如使用了兩個圖片加載庫:Glide和Picasso。
通過查看exploded-aar目錄和External Libraries或者反編譯生成的APK,盡量避免重復庫的大小,減小APP大小。

使用更小的庫

同樣功能的庫在大小上是不同的,甚至會懸殊很大。
如果並無對某個庫特別需求而又對APP大小有嚴格要求的話,比較這些相同功能第三方庫的大小,選擇更小的庫會減小APP大小。

支持插件化

插件化技術支持動態的加載代碼和動態的加載資源,把APP的一部分分離出來了,對於業務龐大的項目來說非常有用,極大的分解了APP大小。
因為插件化技術需要一定的技術保障和服務端系統支持,有一定的風險,如無必要(比如一些小型項目,也沒什麼擴展業務)就不需要了,建議酌情選擇。

Facebook的redex優化字節碼

redex是facebook發布的一款android字節碼的優化工具,需要按照說明文檔自行配置一下。

redex input.apk -o output.apk --sign -s  -a  -p 

下面我們來看看它的效果,僅redex的話,減小了157k:
這裡寫圖片描述

下面我們來看看它的效果,僅redex的話,減小了157k:
這裡寫圖片描述

如果先進行微信混淆,再redex,減小了565k,redex只貢獻了10k:
這裡寫圖片描述

如果先進行redex,在進行微信混淆,減小了711k,redex貢獻了157k:
這裡寫圖片描述

最後一種的效果是最好的,這是很容易解釋的,如果最後是redex的重新打包則浪費了前面的7zip壓縮,所以為了最優效果要注意順序。
另外,據反應redex後會有崩潰的現象,這個要留意一下,我這裡壓縮之後都是可以正常運行的。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved