App瘦身的概念
- App瘦身是指在不减少App功能的前提下,通过一些技巧将打包出来的apk体的体积尽可能减少。
这样做的好处有几个:加快用户下载速度,节省用户下载流量,提升用户下载体验。
如果不进行瘦身,默认打包的apk会包含所有未曾用到的源代码、资源文件等,极大的增加了apk的体积。
App瘦身的常用技巧
- 第一种:配置build.gradle文件,开启minifyEnabled,作用是启用混淆压缩模式,会过滤掉整个项目中未使用到的jar和class文件,对代码进行混淆,从而减少dex文件大小。
- 但是,并不能减少图片资源。
buildTypes {
//增加构建类型
releaseMinifyEnabled {
//开启dex字节码压缩,舍去未使用的jar和class文件
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
//默认release构建类型
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
- 第二种:配置build.gradle文件,开启shrinkResources,作用是将res目录下未使用到的图片文件进行特殊处理,其具体做法是将未使用到的图片全部变成1x1像素的小图,从而减少res目录的大小。
- 弥补minifyEnabled中的不足。
具体做法如下:
shrinkResources {
//启用res资源过滤,会将项目中未使用到的图片变成1x1的小图,从而减少体积
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
- 第三种:配置build.gradle文件,指定resConfigs,作用是指定打包时编译的语言包类型,未指定的其他语言包,将不会打包到apk文件中,从而减少apk体积的大小。
一般我们只支持中文和英文。
defaultConfig {
applicationId "com.example.lxj.appthin"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
//配置打包时编译的语言类型,默认会编译value目录,此处再增加一个中文类型
resConfigs("zh")
}
- 第四种:采用三方工具(如tinypng)来进一步压缩项目中的所有png图片,从而进一步减小apk体积。
- 首先,打开tinypng网站,将项目中的png图片拖拽网页中,自动进行压缩;
- 然后,下载所有经过压缩的图片,替换项目中对应的png图片;
- 总结:该种方式能够极大的减小图片的体积,基本上能减小50%左右,效果非常显著,强烈建议掌握。
- 第五种:采用webp格式的图片替换png和jpg格式的图片
- webp概念:
WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。Facebook Ebay等知名网站已经开始测试并使用WebP格式,国内的京东,淘宝客户端都在使用。webp格式是未来图片格式的趋势。
对于服务器来说,webp格式可以说是必用的格式。对于客户端来说,可以将比较大的png图片替换为webp格式,从而减少apk的体积。
- 如何将得到webp格式的图片?
有2种方式,可以选择让美工在作图的时候直接做成webp格式;也可以选择使用一些webp格式转换工具对当前已有的png图片进行转换。
- 如何将webp格式的图片应用到项目中?
直接将得到的webp格式图片替换项目中的png图片即可。
- webp使用注意事项
Android4.0以及以上才支持webp格式,但是这并没有影响,因为我们开发时的minSDK就是14了,所以不用关
第6种:使用一套资源
这是最基本的一条规则,但非常重要。
对于绝大对数APP来说,只需要取一套设计图就足够了。鉴于现在分辨率的趋势,建议取720p的资源,放到xhdpi目录。
相对于多套资源,只使用720P的一套资源,在视觉上差别不大,很多大公司的产品也是如此,但却能显著的减少资源占用大小,顺便也能减轻设计师的出图工作量了。
注意,这里不是说把不是xhdpi的目录都删除,而是强调保留一套设计资源就够了。
第七条:使用jpg格式
如果对于非透明的大图,jpg将会比png的大小有显著的优势,虽然不是绝对的,但是通常会减小到一半都不止。
在启动页,活动页等之类的大图展示区采用jpg将是非常明智的选择。
第8条:缩小大图
如果经过上述步骤之后,你的工程里面还有一些大图,考虑是否有必要维持这样的大尺寸,是否能适当的缩小。
事实上,由于设计师出图的原因,我们拿到的很多图片完全可以适当的缩小而对视觉影响是极小的
第9条:覆盖第三库里的大图
有些第三库里引用了一些大图但是实际上并不会被我们用到,就可以考虑用1x1的透明图片覆盖。
你可能会有点不舒服,因为你的drawable下竟然包含了一些莫名其妙的名称的1x1图片…
第10条:删除armable-v7包下的so
基本上armable的so也是兼容armable-v7的,armable-v7a的库会对图形渲染方面有很大的改进,如果没有这方面的要求,可以精简。
这里不排除有极少数设备会Crash,可能和不同的so有一定的关系,请大家务必测试周全后再发布。
第11条:删除x86包下的so
与第十条不同的是,x86包下的so在x86型号的手机是需要的,如果产品没用这方面的要求也可以精简。
建议实际工作的配置是只保留armable、armable-x86下的so文件,算是一个折中的方案。
第12条:使用微信资源压缩打包工具
微信资源压缩打包工具通过短资源名称,采用7zip对APP进行极致压缩实现减小APP的目标,效果非常的好,强烈推荐。
详情参考:Android资源混淆工具使用说明原理介绍:安装包立减1M–微信Android资源混淆打包工具建议开启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 <your_application_id>.R.drawable.icon into whitelist.
// because the launcher will get thgge icon with his name
def packageName = <your_application_id>
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签名进行重新混淆打包。
第13条:使用provided编译
对于一些库是按照需要动态的加载,可能在某些版本并不需要,但是代码又不方便去除否则会编译不过。
使用provided可以保证代码编译通过,但是实际打包中并不引用此第三方库,实现了控制APP大小的目标。
但是也同时就需要开发者自己判断不引用这个第三方库时就不要执行到相关的代码,避免APP崩溃。
第14条:使用shape背景
特别是在扁平化盛行的当下,很多纯色的渐变的圆角的图片都可以用shape实现,代码灵活可控,省去了大量的背景图片。
第15条:使用着色方案
相信你的工程里也有很多selector文件,也有很多相似的图片只是颜色不同,通过着色方案我们能大大减轻这样的工作量,减少这样的文件。
借助于android support库可实现一个全版本兼容的着色方案,参考代码:DrawableLess.java
第16条:在线化素材库
如果你的APP支持素材库(比如聊天表情库)的话,考虑在线加载模式,因为往往素材库都有不小的体积。
这一步需要开发者实现在线加载,一方面增加代码的复杂度,一方面提高了APP的流量消耗,建议酌情选择。
第17条:避免重复库
避免重复库看上去是理所当然的,但是秘密总是藏的很深,一定要当心你引用的第三方库又引用了哪个第三方库,这就很容易出现功能重复的库了,比如使用了两个图片加载库:Glide和Picasso。
通过查看exploded-aar目录和External Libraries或者反编译生成的APK,尽量避免重复库的大小,减小APP大小。
第18条:使用更小的库
同样功能的库在大小上是不同的,甚至会悬殊很大。
如果并无对某个库特别需求而又对APP大小有严格要求的话,比较这些相同功能第三方库的大小,选择更小的库会减小APP大小。
第19条:支持插件化
过去的一年,插件化技术雨后春笋一样的都冒了出来,这些技术支持动态的加载代码和动态的加载资源,把APP的一部分分离出来了,对于业务庞大的项目来说非常有用,极大的分解了APP大小。
因为插件化技术需要一定的技术保障和服务端系统支持,有一定的风险,如无必要(比如一些小型项目,也没什么扩展业务)就不需要了,建议酌情选择。
第20条:精简功能业务
这条完全取决于业务需求。
从统计数据分析砍掉一些没用的功能是完全有可能的,甚至干脆去掉一些花哨的功能出个轻聊版、极速版也不是不可以的。