1. 程式人生 > >2M-APK瘦身實測可行又便捷的方法 (應用上架 陣前磨槍)

2M-APK瘦身實測可行又便捷的方法 (應用上架 陣前磨槍)

新專案上線,新應用原始apk大小在6.9M左右,然後公司和第三方運營公司合作,加入其提供的第三方SDK,瞬間apk體積增大3M;接著為了應用上線後的安全性,對應用進行了加固處理,套了一層殼之後,應用又增大了1.7M,最後上線之前包的體積已經超過10M,計算器這一工具類的應用包體積超過10M就沒有很強的競爭力了,所以減小包體積的工作勢在必行。

下面是博主實際運用到的一些方法,沒有囊括所有的方案,但都是有效的方案:

1).刪除專案中無用的資源

Menu - >Refactor ->Remove unused resources

AS搜尋一段時間之後會在下方彈出提示框,點選“do refactor”就可以將專案中無用的資原始檔全部清除,包括圖片,各種xml檔案。注意:機器沒有智慧到那種程度,所以直接刪除可能會導致一些錯誤,使得之後編譯不通過,所以建議在直接刪除之前使用快捷鍵“alt + F7

”檢查該資原始檔在專案中使用的地方,確定確實無用之後在進行刪除。

2).清除專案中無用的import包

Menu - >Code ->Optimize Imports  | 專案根目錄下右鍵->Optimize Imports

以上是直接去掉整個專案中的import包,若在某個檔案中去除可使用快捷鍵“ctrl+alt+o”。

也可在設定裡直接設定為自動清除無用的import包(可自動匯入包,當然也可以設定為自動刪除包)。

Setting - >Editor - >General - >Auto Import - >Optimize imports on the fly

以上兩步操作完之後,整個應用包減小0.7M。

3)包體分析 (Android Studio 2.2以上)- 從內到外瞭解

Menu - >build->Analyze APK

①lib/ -> 存放so檔案,可能會有armeabi、armeabi-v7a、arm64-v8a、x86、x86_64、mips,大多數情況下只需要支援armabi與x86的架構即可,如果非必需,可以考慮拿掉x86的部分;

②res/ -> 存放編譯後的資原始檔,例如:drawable、layout等等;

③assets/ -> 應用程式的資源,應用程式可以使用AssetManager來檢索該資源;

④META-INF/ -> 該資料夾一般存放於已經簽名的APK中,它包含了APK中所有檔案的簽名摘要等資訊;

⑤classes(n).dex -> classes檔案是Java Class,被DEX編譯後可供Dalvik/ART虛擬機器所理解的檔案格式;

可以看到佔用空間的主要是程式碼、圖片、資源和lib和assert檔案,主要方向精簡程式碼、壓縮圖片、去除無用的庫、減少asserts裡面檔案。

有了方向之後,那麼開始進行瘦身:

a.asserts資料夾內去除佔用空間較大的字型檔案,既使得包的體積減小(一個字型檔案100-200k),又使得應用字型變得更為統一;

b.開啟資源壓縮

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

minifyEnabled 設為true時會自動對程式碼進行清理,打包時去掉無用的程式碼部分,所以編譯速度會受到影響;

shrinkResources設為true時打包會自動根據minifyEnabled 為true時去掉的程式碼部分再次去掉該程式碼部分相關的資原始檔部分,注意二者是配合使用的。

注:build.gradle中配置二者時只是在打包檔案中去掉了無用的部分,專案中還是實際存在的。

c.語言資源優化,原專案中產品經理要求配置三種語言:中文 英文 法語,最終上線前為包體積做考慮,只啟用英語一門語言配置(應用是釋出在谷歌應用市場)。

android {
    ...
    defaultConfig {
        ...
        resConfigs "en"
    }
    ...
}

如果不做任何配置的話,最終APK包中會包含專案中所有已翻譯語言字串,無論應用的其餘部分是否翻譯為同一語言,可以通過resConfig來配置使用哪些語言,從而讓構建工具移除指定語言之外的所有資源。

d.圖片壓縮,原本專案中使用的圖片都是32*32的png圖片,後來為清晰度的考慮將圖片同一替換成72*72的png,結果每張圖片都有200k左右,這裡推薦使用tinypng網站進行圖片無失真壓縮,下面這張圖從190k壓到1.6k,肉眼基本看不出任何區別;

這兩張圖示 一張被壓縮了97%,你相信嗎?

e.優化classes.dex,這裡無定式方法,主要是提供一些思路 —— 時刻保持良好的程式設計習慣和對包體積敏銳的嗅覺,去除重複或者不用的程式碼,慎用第三方庫,選用體積小的第三方SDK等等。

以上四步操作完之後,整個應用包減小0.5M。

4)APK瘦身放大招 - AndResGuard的使用

①概念:AndResGuard是一個縮小APK大小的工具,它的原理類似Java Proguard,但是隻針對資源。它會將原本冗長的資源路徑變短,例如將res/drawable/wechat變為r/d/a(是的,如同混淆一樣的abc,通過進一步混淆res資源夾來減小包體積)。

②配置

專案根目錄下build.gradle中,新增外掛的依賴:

 dependencies {
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.10'
    }

專案根目錄中build.gradle中,再新增白名單配置:

apply plugin: 'AndResGuard'
buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.10'
    }
}

andResGuard {

    mappingFile = null
    use7zip = true
    useSign = true
    keepRoot = false

    whiteList = [
            // your icon
            "R.drawable.icon",
            // for fabric
            "R.string.com.crashlytics.*",
            // for umeng update
            "R.string.tb_*",
            "R.layout.tb_*",
            "R.drawable.tb_*",
            "R.drawable.u1*",
            "R.drawable.u2*",
            "R.color.tb_*",
            // umeng share for sina
            "R.drawable.sina*",
            // for google-services.json
            "R.string.google_app_id",
            "R.string.gcm_defaultSenderId",
            "R.string.default_web_client_id",
            "R.string.ga_trackingId",
            "R.string.firebase_database_url",
            "R.string.google_api_key",
            "R.string.google_crash_reporting_api_key",

            //友盟
            "R.string.umeng*",
            "R.string.UM*",
            "R.layout.umeng*",
            "R.drawable.umeng*",
            "R.id.umeng*",
            "R.anim.umeng*",
            "R.color.umeng*",
            "R.style.*UM*",
            "R.style.umeng*",

    ]
    compressFilePattern = [
            "*.png",
            "*.jpg",
            "*.jpeg",
            "*.gif",
            "resources.arsc"
    ]
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.2.10'
    }
}

其中whiteList(白名單)中指定不需要進行混淆的資源路徑規則,主要是一些第三方SDK,因為有些SDK的程式碼中引用到對應的資原始檔,如果對其進行混淆,會導致找不到對應資原始檔,出現crash,所以不能對其資原始檔進行混淆。由於公司的專案中使用到了友盟和融雲,所以將這兩個SDK加入白名單,更多的白名單可以檢視:

③打包

不再使用AS自帶打包方法,而是使用gradle的打包方法,AS右側點選Gradle開啟Gradle任務列表:

打release包,只需要雙擊resguardRelease,開始打包(時間較長),執行完畢後,可以在app目錄下的/build/output/apk/release/AndResGuard_{apk_name}/ 資料夾中找到混淆後的Apk,其中app-release_aligned_signed.apk為進行混淆並簽名過的apk,雙擊檢視該apk,再次開啟res資料夾就會發現所有的檔名都已經再次混淆了。

操作完這一步之後,整個apk減小了0.8M

通過以上的一些apk瘦身常用方法,最終包減小了2M左右,值得一提的是,如果使用一種瘦身方法沒有明顯的效果時,就可以放棄再尋找其他方法,不要死磕(別問我為什麼這樣說)。

PS:臨時抱佛腳,應用上架前被附加了那麼多東西,然後才開始做apk瘦身,博主多少有些無奈。不過學到了很多!以後不會被弄的手忙腳亂的了。