一、概述
为什么APK要瘦身。APK越大,在下载安装过程中,他们耗费的流量会越多,安装等待时间也会越长;对于产品本身,意味着下载转化率会越低(因为竞品中,用户有更多机会选择那个体验最好,功能最多,性能最好,包最小的),所以APK的瘦身优化也很重要,本篇博客将讲述APK瘦身的相关内容。
二、APK包分析
在Android Studio工具栏里,打开build–>Analyze APK, 选择要分析的APK包,如下图:

lib文件夹:用于存放应用需要的库文件;classes.dex文件:所有的Java代码最终都是转化成dex文件,运行在Android虚拟机上;res文件夹:存放所有的资源文件;resource.arsc文件:存放所欲资源文件的id映射;META-INF文件夹:存放几个签名校验的相关文件,用于保证APK的完整性和安全性;AndroidManifest.xml文件:Android应用的全局配置文件;assets文件夹:用于保存需要保持原始文件的资源文件。
其中,在安装包中占比较大的包括:dex文件、res文件夹、assets文件夹、lib文件夹以及resource.arsc文件。所以,接下来的瘦身优化就是让这些文件变小,以此达到瘦身的目的。
三、瘦身方案
资源瘦身
对于绝大对数APP来说,只需要取一套设计图就足够了。鉴于现在分辨率的趋势,建议取720p的资源,放到xhdpi目录。
1.尽量只保存一份图片资源
2.使用 Drawable XML、Color、.9 PNG 代替 PNG
- 一些情况下,我们可以考虑使用
Drawable XML来代替PNG,如:渐变的背景图,用几行XML就可以描绘出来,何必使用几十到上百K的PNG文件; - 用
Color代替PNG,如:纯色的背景; - 从性能上看,比起使用图片资源需要先将其生成
Bitmap再传到底层交由GPU渲染,用Drawable XML和Color则更加高效,它是直接将Shape信息传到底层由GPU进行渲染,CPU和 内存的占用会更少; - 用
.9 PNG代替PNG,场景很多,不举例了;
3.使用 JPG 代替 PNG
用 JPG 代替 PNG,由于 JPG 没有 Alpha 通道,所以文件更小,适用于不需要透明度的图片可以考虑。
4.谨慎使用 WebP 代替 PNG
由于 WebP 效果好,且相同效果下, WebP 文件比 PNG 文件要小得多 ,所以,网上很多人说使用 WebP 代替 PNG,对此,我保持异议。理由如下:
WebP在Android端,最低只支持 4.0 ,要兼容 4.0 以下的环境需要额外引入兼容库,反而增大安装包体积;Android Studio不支持预览WebP图片,引用WebP的布局文件也无法预览显示;- 解压了
BAT们的应用,以及同类竞品,基本没有发现在资源文件中用WebP的;
官方介绍:https://developers.google.com/speed/webp/docs/precompiled
5.有损编码格式的音频文件代替无损格式的音频文件
- 无损格式:WAV,PCM,ALS,ALAC,TAK,FLAC,APE,WavPack(WV)
- 有损格式:MP3,AAC,WMA,Ogg Vorbis
实际开发中需要使用音频文件尽量采用 MP3、Ogg 这种有损格式,尽量不要用 WAV、PCM 这种无损音频。
6.移除无用的资源
android {
buildTypes {
release {
shrinkResources true
}
}
}
7.清理无用资源
版本迭代过程中,不但有废弃代码冗余,肯定会有无用的图片存在。 在
build.gradle里面配置shrinkResources true,在打包的时候会自动清除掉无用的资源,但经过实验发现打出的包并不会,而是会把部分无用资源用更小的东西代替掉。
注意,这里的“无用”是指调用图片的所有父级函数最终是废弃代码,而
shrinkResources true只能去除没有任何父函数调用的情况。
这里使用 Android Studio 自带的工具来清理无用资源:

8.删除无用的语言资源
大部分应用其实并不需要支持几十种语言的国际化支持。还好强大的gradle支持语言的配置,比如国内应用只支持中文:
android {
defaultConfig {
resConfigs "zh"
}
}
9.使用Tinypng有损压缩
Tinypng工具只支持上传PNG图片到官网上压缩,然后下载保存,在保持alpha通道的情况下对PNG的压缩可以达到1/3之内,而且用肉眼基本上分辨不出压缩的损失。
Tinypng的官方网站:http://tinypng.com/
10.缩小大图
如果经过上述步骤之后,你的工程里面还有一些大图,考虑是否有必要维持这样的大尺寸,是否能适当的缩小。
事实上,由于设计师出图的原因,我们拿到的很多图片完全可以适当的缩小而对视觉影响是极小的。
11.覆盖第三库里的大图
有些第三库里引用了一些大图但是实际上并不会被我们用到,就可以考虑用1x1的透明图片覆盖。
你可能会有点不舒服,因为你的drawable下竟然包含了一些莫名其妙的名称的1x1图片
12.精简SO
- 删除
armable-v7包下的so;- 基本上armable的so也是兼容armable-v7的,armable-v7a的库会对图形渲染方面有很大的改进,如果没有这方面的要求,可以精简。
- 这里不排除有极少数设备会Crash,可能和不同的so有一定的关系,请大家务必测试周全后再发布。
- 删除x86包下的
so- x86包下的so在x86型号的手机是需要的,如果产品没用这方面的要求也可以精简。 建议实际工作的配置是只保留armable、armable-x86下的so文件,算是一个折中的方案。
在模块的build.gradle的defaultConfig下加入以下ndk配置:
ndk {
moduleName "myNativeLib"
ldLibs "log", "z", "m"
abiFilters "armeabi", "x86", "armeabi-v7a", "x86_64", "arm64-v8a"
}
- moduleName是随便写的,与将来在Java类中使用System.loadLobrary(“本地库名称”);以及生成的.so文件名称对应;
- ldLibs是要用到的jni库,一般由google提供,比如上边引入的log库可以让我们在C代码中使用LogCat日志;
- abiFilters指的是我们要生成哪些平台的so文件,这里生成arm平台和x86平台。
13.使用微信资源压缩打包工具
微信资源压缩打包工具通过短资源名称,采用7zip对APP进行极致压缩实现减小APP的目标,效果非常的好,强烈推荐。
建议开启7zip,注意白名单的配置,否则会导致有些资源找不到,官方已经发布AndResGuard到gradle中了,非常方便:

14.矢量图
矢量图是由点与线组成,和位图不一样,它再放大也能保持清晰度,而且使用矢量图比位图设计方案能节约30~40%的空间,现在谷歌一直在强调扁平化方式,矢量图可很好的契合该设计理念。
-
优势
- (1)占用存储空间小
- (2) 无极拉伸不会出现锯齿,可以照顾不同尺寸的机型
- (3)Android Studio自带很多资源,减小UI工作量
-
劣势
- (1) 只支持5.0及以上系统
- (2) 与位图相比多了一层计算,需消耗更多性能
- (3) 不支持.9图
- (4)不适合表现真实照片和复杂图形,一般使用在简单的icon和动画上
15.使用shape背景
特别是在扁平化盛行的当下,很多纯色的渐变的圆角的图片都可以用shape实现,代码灵活可控,省去了大量的背景图片。