APK瘦身便是对APK大小进行压缩策略,减少APK安装包大小,更小的安装包更有助于吸引用户安装。前一段时间我司某一App进行APK的瘦身,最终也达到了减少10M的目标,现作一个简单的总结记录。android
须要对一个App进行瘦身,首先最重要的就是对App大小有一个大体的了解,最直观看到App的大小就是经过Android Studio自带的Analyzer进行APK的分析。使用方法:web
一、将一个apk拖动到Android Studio的编辑器窗口
二、在Project窗口中,双击build/output/apks/目录下的apk
三、在菜单栏中选择选择Build > Analyze APK,而后选择要分析的apk
复制代码
获取如上图1所示的APK Size分析图以后,咱们就能够针对这里面的目录进行针对性的优化。面试
如图最上方所示的APK Size就是咱们应用打包以后的大小,Download Size则是上传到Google Play以后,用户下载的大小。因此咱们通常能够只针对前一项的APK Size进行对比。安全
从上图Analyzer能够发现,一个APK主要包含以下目录:bash
除此以外,还包含了以下的文件:微信
知道了APK的组成部分,那么咱们就能够针对这些文件/文件夹进行针对性的优化,每一个App都不同,可是方法都是大同小异,本文讲述瘦身策略也是针对这些目录和文件进行优化,这样能够显得更加有条理性。架构
Android系统如今支持7种CPU架构,每一种都关联着对应的ABI(二进制接口,Application Binary Interface),而每一种ABI都定义了二进制文件(尤为是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库等。因此若是咱们的App须要适配不一样的CPU架构的话,以下图2所示,就须要放入不一样架构的文件夹下都放入不一样的so文件,在打包时,这些so都会放在lib目录下。由此,若是咱们想减少lib目录的大小,无非就以下一些常见的策略。app
对App引入的so文件进行确认哪些是不须要的,哪些是能够进行裁剪压缩的,哪些是能够避免引入的。例如若是引入的so须要下载上传功能而多引入了一个cURL库致使so增大,这时就可让Java层代码定义接口,让so来调用,从而避免引入cURL库;再如Fresco库,若是不须要webP图,或者不须要webP动图功能,而后减小Fresco库的依赖,一样能够减少so的大小。编辑器
Android系统如今支持不少种CPU架构(如mips、arm、x86等),市面上主流机型都是arm架构,x86和mips类型极少。因此能够有选择地保留某些架构的so,从而下降lib文件夹的大小。可是我建议你在开始前先对用户手机的cpu型号进行一次统计,分析自身App对应架构手机的占有率,这样你才能大胆的进行操做,通常只保留armeabi或者armeabi-v7a便可。操做也是比较简单,只须要在根目录的build.gradle下配置:函数
android {
buildTypes {
ndk {
abiFilters "armeabi-v7a"
}
}
}`
复制代码
若是你的App须要支持多种架构,那么就能够在abiFilters里面把多种架构加进去,固然你也能够只保留一种,而后分渠道打包,如Google Play就支持arm和x86等多个渠道打包。
res目录通常也是占APK Size大头的一个目录,以下图,这个目录通常都是图片资源占空间比较多,尤为当App为了适配多种分辨率而存放了多套图时,这时候就会致使res目录打下会很是大。而这个目录的优化方式也是比较多,下面就简单列举一下:
由于Android设备在加载图片时会优先加载对应分辨率文件夹下的图片,若是对应分辨率文件下没有所要的图片,则找高分辨率对应文件夹下的图片。那是否是咱们把图片放在最高分辨率的文件夹下就能够了呢?不是的!由于若是这样会致使低分辨率手机加载图片时会消耗更多的内存,并且是指数级别增加的,因此若是盲目地放在一个目录是不合适的。目前不一样分辨率对应优先加载的文件夹中图片以下,若是是针对国内用户的App能够只保留xxhdpi目录,而若是是东南亚市场的App则能够只保留xhdpi。
320*240 ldpi
480*320 mdpi
800*480 hdpi
1280*720 xhdpi
1920*1080 xxhdpi`
复制代码
针对一些非重要的图片,能够选择动态在线加载,严格来讲,非首页的图片均可以动态加载,固然,为了提高用户体验,咱们会把图片放在本地。可是,一些使用场景很是小或者大小较大的图片,大胆删掉,选择动态加载吧!
可使用一些图片压缩网站或者工具压缩你的资源文件吧,例如TinyPng、ImageOptim、Zopfli、智图等。
若是你的App只支持Android4.0以上的话,能够把png格式的图片转为webp,相同画质下体积更小。
在多人开发过程当中,一般都会有漏删无用资源的问题,图片资源也不例外,例如须要删除一个模块的代码时,很容易就会漏删资源文件,因此能够按期使用lint检测出无用的资源文件,原理这里不做介绍,使用方法很是简单,能够直接在AS里面使用,以下图所示。注意:lint检查出来的资源都是无直接引用的,因此若是咱们经过getIdentifier()方法引用文件时,lint也会标记为无引用,因此删除时注意不要删除经过getIdentifier()引用的资源。
Analyze -> Run Inspection by Name -> 输入:Unused resources ->
跳出弹框选择范围便可
复制代码
shrinkResources是在编译过程当中用来检测并删除无用资源文件,也就是没有引用的资源,minifyEnabled 这个是用来开启删除无用代码,好比没有引用到的代码,因此若是须要知道资源是否被引用就要配合minifyEnabled使用,只有二者都为true时才会起到真正的删除无效代码和无引用资源的目的。打开方式也是很是简单,在build.gralde文件里面打开便可:
android {
buildTypes{
minifyEnabled true
shrinkResources true
}
}`
复制代码
assests目录存放的一般是一些经过AssetManager可以检索到的资源,包括MP三、视频、字体、webp的资源,各个App存放内容都很大不相同,列举一些经常使用的优化方案。
中文字体通常都比较大,由于字体文件包含了中文好几千个汉字,可是咱们实际上在App中并不会所有都使用,甚至咱们只用到其中的几个字,这时候咱们就能够把字体文件进行删减,在Github上面有一个字体提取工具FontZip,使用方法也是很是简单,有兴趣能够去star一下。
一些MP三、视频、Webp等资源能够在使用到时再进行下载,不须要放在本地。
一些MP三、视频、Webp等资源若是必须放在本地,能够压缩成zip文件或者使用7zip进行压缩,在使用到时再进行解压,减少空间的占用。
该目录下的MANIFEST.MF、CERT.SF、INDEX.LIST、CERT.RSA等文件主要是存放一些APK文件加密后的信息,用以校验APK的完整性和安全性,这个目录没有太好的优化方式,并且文件通常也比较小,不会超过1M。
这个文件包含全部能够被编译的位于res/values/目录下的XML资源,以下图5所示是淘宝APK的resources.arsc文件,像图片的引用名字、layout文件的引用名字、string资源等都被编译到了这个文件里面。
大部分应用都不须要支持几十种上百种语言,因此在咱们引用一些第三方库时(如Google、Facebook的库),它们每每带有上百种多语言资源,而大部分多语言对于咱们本身的应用是没有用处的,咱们只须要在build.gralde里面进行以下配置便可完成无用语言资源的删除,这样在打包的时候就会排除私有项目、android系统库和第三方库中非中文的资源文件了,效果仍是比较显著的。
android {
//...
defaultConfig {
// 只保留中文
resConfigs "zh"
}
}`
复制代码
AndResGuard是一个帮助你缩小APK大小的工具,他的原理相似Java Proguard,可是只针对资源。他会将本来冗长的资源路径变短,例如将res/drawable/wechat变为r/d/a。详细使用方法参照Github,很简单有效地减少resources.arsc文件大小。以下图6和图7所示,图6是压缩前的效果,图7是压缩完的效果,若是是资源比较多的App,压缩效果也是立竿见影。
andResGuard {
mappingFile = null
use7zip = true
useSign = true
keepRoot = false
whiteList = [
//for your icon
"R.drawable.icon",
//for fabric
"R.string.com.crashlytics.*",
//for umeng update
"R.string.umeng*",
"R.string.UM*",
"R.layout.umeng*",
"R.drawable.umeng*",
//umeng share for sina
"R.drawable.sina*"
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"resources.arsc"
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.1.9'
//path = "/usr/local/bin/7za"
}
}`
复制代码
Dalvik是Android平台运行时的环境,可是Dalvik虚拟不支持直接执行Java的字节码,因此会对编译生成的 .class 文件进行翻译、重构、解释、压缩等处理,这个处理过程是由 dx 进行处理,处理完成后生成的产物会以 .dex 结尾,称为Dex文件。
像淘宝、微信这些App,若是咱们分析它们的APK能够发现,它们有多个Dex文件,以下图8所示,这是由于单个Dalvik Excutable(DEX)字节码文件内的方法数不能够超过65536个,因此须要DEX分包配置来避免这个限制,使应用可以构建并读取DEX文件。
Proguard是一款免费的Java类文件压缩器、优化器和混淆器,Android Studio已经集成了这个工具,只要通过简单的配置,便可完成,以下代码所示,在build.gradle里面设置minifyEnabled为ture,同时在proguardFiles指向proguard的规则文件便可。
android {
buildTypes{
minifyEnabled true
proguardFiles 'proguard.cfg'
}
}`
复制代码
App瘦身是一个长期的过程,建议能够进行每一个版本对APK大小进行监控,列出增长和减少的点,作到持续的统计和追踪,从而给公司带来效益。
按期分享Android高级技术和面试分享,欢迎关注,喜欢文章的朋友点个赞叭~