Android APK 瘦身实践

作者 |  吴小龙同学

声明 | 本文是  吴小龙同学 原创,已获授权发布,未经原作者允许请勿转载



前言

现在 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


与之相关

加快 apk 的构建速度,如何把编译时间从 130 秒降到 17 秒

Android 优化 APP 构建速度的 17 条建议




END


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值