微信号:gh_f86c241826a6

介绍:不止于技术分享,不取悦他人,写给懂的你看~

Android APK瘦身实践

2017-03-19 18:35 肥大龙


现在APK动不动就是几十兆,当用户连接到2G和3G网络,或者按流量收费的设备是多么的浪费,这篇文章介绍了如何对APK进行瘦身,帮助更多用户毫不犹顾忌地下载你们的APP。

以我的个人APP【 微言 】实践,未做任何处理,APK大小 11712 KB= 11.43 MB。


开启minifyEnabled混淆代码


在app/build.gradle打开minifyEnabled:

android {
    buildTypes {
        release {
            minifyEnabled true
        }
    }
}

在app/proguard-rules.pro编写混淆规则,根据自己项目依赖的库一一混淆,这里就不提供具体混淆代码了。

经过混淆,APK大小 10906 KB,效果很明显,一下子瘦了0.78 MB。


开启shrinkResources去除无用资源


在app/build.gradle打开shrinkResources:

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
        }
    }
}

shrinkResources依赖于minifyEnabled,必须和minifyEnabled一起用,就是打开shrinkResources也必须打开minifyEnabled。

APK大小 10903 KB。


删除未使用到xml和图片


如何知道哪些xml和图片未被使用到?使用Android Studio的Lint,步骤:点击菜单栏 Analyze ->  Run Inspection by Name -> unused resources ->  Moudule ‘app’ -> OK,这样会搜出来哪些未被使用到未使用到xml和图片,如下:

经过删除,APK大小 10891 KB。


删除未使用到代码


同样使用Android Studio的Lint,步骤:点击菜单栏 Analyze ->  Run Inspection by Name -> unused declaration ->  Moudule ‘app’ -> OK

经过一番清理,APK大小 10880 KB,才瘦了11KB,我以为能瘦很多,不过,平时必须保持良好的编码习惯,哪些没有使用到的代码还是删删掉吧,不要想着以后还会用到。

重复操作上一步和这一步,会有意外的发现哦。


png图片格式转成jpg


将一些大图的格式转成jpg格式,将会有效减小图片的体积,我的APP大图不是很多。

更改格式后,APK大小 10762 KB。


使用vector


微言是我很早就已经做得app,一开始图标都是图片,且每个drawable都有相应尺寸的图标,占了不少大小,后来部分用vector代替了图片。注意一点,Button在xml里设置app:srcCompat居然无效,只能在代码里设置:

button.setImageResource(R.drawable.ic_favorite_border_black_24dp)。

APK大小 10754 KB。


使用shape作为背景


很多点击效果可能会使用到图片,可以换成shape是实现,我查看了下,微言APP都是shape实现的,Good。


使用TinyPng


如果对png图片格式转成jpg,减小效果还不满意,直接使用TinyPng智能有损压缩技术,网址:https://tinypng.com/ ,压缩效果:

对于图片资源很多的APP,APK瘦身效果不要太好。

APK大小 10341 KB。


配置resConfigs


如果APP支持中文,可以配置resConfigs,只支持中文

android {
    defaultConfig {
        ...
        //语言资源,只支持中文
        resConfigs "zh"
    }
}

APK大小 10243 KB。


使用微信Android资源混淆工具


微信AndResGuard是一个帮助你缩小APK大小的工具,详情:Android资源混淆工具使用说明

使用方法:


>>>>

Project/build.gradle



buildscript {    repositories {        jcenter()    }    dependencies {        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.0'    } }


>>>>

app/build.gradle

apply plugin: 'AndResGuard'
def supportVersion = "25.0.0"
android {
    ...
    signingConfigs {
        release {
            storeFile file('keystore/android.keystore')
            storePassword '123456'
            keyAlias 'android.keystore'
            keyPassword '123456'
        }
        debug {
            storeFile file('keystore/android.keystore')
            storePassword '123456'
            keyAlias 'android.keystore'
            keyPassword '123456'
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}

repositories {
    flatDir {
        dirs 'aars'
    }
}

andResGuard {
    // mappingFile = file("./resource_mapping.txt")
    //mappingFile用于增量更新,保持本次混淆与上次混淆结果一致;
    mappingFile = null
    //uss7zip为true时,useSign必须为true;
    use7zip = true
    //useSign为true时,需要配置signConfig;
    useSign = true
    //打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字;
    keepRoot = false
    //whiteList添加在代码内部需要动态获取的资源id,不混淆这部分;
    whiteList = [
            // for your icon
            "R.drawable.icon",
            // for fabric
            "R.string.com.crashlytics.*",
            // for umeng update
            "R.string.umeng*",
            "R.string.UM*",
            "R.string.tb_*",
            "R.layout.umeng*",
            "R.layout.tb_*",
            "R.drawable.umeng*",
            "R.drawable.tb_*",
            "R.anim.umeng*",
            "R.color.umeng*",
            "R.color.tb_*",
            "R.style.*UM*",
            "R.style.umeng*",
            "R.id.umeng*",
            // 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",
            // umeng share for facebook
            "R.layout.*facebook*",
            "R.id.*facebook*",
            // umeng share for messager
            "R.layout.*messager*",
            "R.id.*messager*",
            // umeng share commond
            "R.id.progress_bar_parent",
            "R.id.webView"
    ]
    //用来指定文件重打包时是否压缩指定文件;
    compressFilePattern = [
            "*.png",
            "*.jpg",
            "*.jpeg",
            "*.gif",
            "resources.arsc"
    ]
    //sevenzip可使用artifacr或path,path指本地安装的7za(7zip命令行工具)。
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.2.0'
        //path = "/usr/local/bin/7za"
    }
}

AndResGuard打包命令行:gradlew resguardRelease,最终的混淆APK会生成在{App}/build/output/apk/AndResGuard目录下。

APK大小 10035 KB= 9.79 MB。


结尾


最终APK瘦身 11.43 - 9.79 = 1.63 MB,瘦身效果不是很明显,说明:

1、我的这个APP毕竟不是商业项目,本身就不大;
2、我的编码习惯可以,没有多少冗余代码和无用资源,哈哈。
大家可以将你们的APK按照这些方法过一遍,看能瘦多少。
瘦身还有其他方法,生命不息,折腾不止。


参考


官方文档Reduce APK Size

https://developer.android.google.cn/topic/performance/reduce-apk-size.html

Android APP终极瘦身指南
http://jayfeng.com/2016/03/01/Android-APP%E7%BB%88%E6%9E%81%E7%98%A6%E8%BA%AB%E6%8C%87%E5%8D%97/

AndResGuard资源混淆

http://www.jianshu.com/p/7ffea26c9fd8



 
吴小龙同学 更多文章 Android APP启动优化 使用DownloadManager进行版本更新(兼容7.0) 提问:能否分享一下你学习和开发Android 的经验? 异乡人 不要在该奋斗的年纪选择了安逸
猜您喜欢 他状告百度:精准推荐触犯隐私!法院二审为何改判? Folly源码分析系列(一) — ThreadLocalPtr 我们给摩拜和ofo们算了笔账,3000万辆单车订单能覆盖中国多少城镇? 为什么这么多「毛派企业家」? 七大关键词 详解微信世界的规则