背景
脸书的产品经理和攻城狮们曾经为了检测自家Android客户端在发展中国家的性能去了一趟非洲。在当地使用Facebook的最新版本的Android客户端,测试的结果的确让他们印象深刻,总结起来就是网络又差又贵的同时手机还坑:)
所以说,除去对性能、数据处理效率以及网络方面的优化,对于APK大小的处理也是刻不容缓的啊哈哈哈。在省流量的同时可以提升下载安装速度,最重要的是减少了占据的存贮空间。
-
保持良好的编码习惯,摆脱不需要的依赖库
随着项目的进展,保持一个clean的代码变得愈发困难。事实上,一个庞大的项目里都存在着无用的代码片段。我们可以借助一些开发工具来进行清理。
-
Proguard
<code>Proguard</code>是一个极其强大的工具,在编译时优化和减少代码。通过所有代码路径检测出哪些代码片段是未使用的,从根本上降低apk的大小。重命名变量、类和接口,使代码更加轻量。
但与此同时,<code>Proguard</code>在默认情况下,打破了应用严重依赖反射,需找到不能混淆的代码在配置文件中注明。
-
利用工具UCDetector(eclipse 工具)扫描
-
通过Inspect Code删掉没有用到的资源
可以选择InSpectCode范围
在Inspection栏目中看到检查的结果
-
借助微信提供的资源文件混淆工具AndResGuard,进一步压缩资源文件所占用的空间
-
Facebook的redex优化字节码工具
先进行redex,再进行微信混淆,效果更佳
-
Lint
当你的资源文件中存在未使用的图片时,<code>Proguard</code>只会去除掉r文件中的引用,保持相关的图像。<code>Lint</code>静态代码分析器,发现所有未使用的资源。
但<code>Lint</code>不能检测出asset下的文件,因为该目录下的文件不会像XML、java文件被预编译,而是通过文件名进行。因此,<code>Lint</code>不能确定asset下的文件是否被使用,需要开发人员自行对asset目录下文件进行判断。
-
尽可能重用
在<code>ListView</code>和<code>RecycleView</code>中,重用可以保持平滑滚动性能。同时,重用也可以帮你减小apk的大小。
通过着色方案我们能大大减轻这样的工作量,减少这样的文件。借助于android support库可实现一个全版本兼容的着色方案。
如果遇到上面这种情况,可以手工转一转
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_arrow_expand"
android:fromDegrees="180"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="180" />
```
-
减少资源配置
安卓开发往往依赖外部库的使用,但这些资源库附带所有资源,包括我们不需要用到的。
-
语言资源
对于大多数的应用,并不需要支持几十种的国际化。对语言资源进行配置,也可以达到应用瘦身的目的。
android { defaultConfig { ... resConfigs "en","zh" ... } }
-
在线化素材库
如果APP支持素材库(比如聊天表情库)的话,可以考虑在线加载模式,但与此同时也会增加代码的复杂度以及APP的流量消耗。
-
避免功能重复库的使用,尽量使用更加轻量的库
-
支持插件化
apk解压之后

文件/目录 | 作用 |
---|---|
Androidmanifest.xml | 清单文件 |
assets | 配置文件,放置一些本地资源,如html,可使用<code>AssetManager</code>检索 |
classes.dex | 编译后字节码文件 |
lib | 存放特定平台使用的编译后的.so文件,每个子文件夹对应一个特定平台 |
META-INF | 包含<code>CERT.RSA</code>,<code>CERT.SF</code>,<code>MANIFEST.MF</code>,存放的签名信息,用于保证系统安全和APK文件完整性 |
res | 存放没有编译到<code>resources.arsc</code>文件中的资源文件 |
resources.arsc | 编译后的二进制资源文件。res/values/目录下所有XML内容。打包工具对XML内容进行提取,编译为二进制,并进行分类。XML内容包含不同语言的strings和styles,同时包含没有被直接打包至<code>resources.arsc</code>文件的其他文件路径,如布局文件和图片文件。 |
classes.dex 源码
- 代码混淆
- 混淆后的代码将较长的文件名、实例、变量、方法名等进行简化,实现字节长度上的优化
- 但混淆较耗时,需找到不能混淆的代码在配置文件中注明,不方便调试
- 开启shrinkResources去除无用资源
resources.arsc资源文件
涉及资源id,可借助Inspect Code删除不必要资源
res资源文件夹
图片、音视频、多媒体资源主要放在res和assets之下
图片:
从内存占用和适配的角度考虑,尽量使用同一套图片
使用tinypng(有损压缩)、pngquant、ImageOptim、mozjpeg等图片压缩工具
代码替代图片
如压缩后图片质量不符合预期,可使用图片格式转换工具iSparta。PS:对于非透明的大图,jpg将会比png的大小有显著的优势.
使用webp格式图片
webp作为一种新的图片格式,支持透明度,压缩比比jpg更高但显示效果却不输于jpg,官方评测quality参数为75均衡最佳。(从Android 4.0+开始原生支持,但是不支持包含透明度,直到Android 4.2.1+才支持显示含透明度的webp。如果应用需要兼容Android 2.3,那么需要额外的引入 .so 文件,apk的体积自然也会增加……)
使用.9图减少资源大小,易于长期维护
引进VectorDrawable(矢量图)和svg(Scalable Vector Graphics可缩放矢量图)
VectorDrawable的颜色是单一的颜色,如果是颜色比较复杂,那么vector很明显就不合适了。
对于图片的使用,Google的建议,简单来说就是:VD->WebP->Png->JPG
- 如果是纯色的icon,那么用svg
- 如果是两种以上颜色的icon,用webp
- 如果webp无法达到效果,选择png
- 如果图片没有alpha通道,可以考虑jpg
音视频:
如果raw文件夹下有音频文件,尽量不要使用无损的音频格式,比如wav。可以考虑相比于mp3同等质量但文件更小的opus音频格式
- 无损格式:WAV,PCM,ALS,ALAC,TAK,FLAC,APE,WavPack(WV)
- 有损格式:MP3,AAC,WMA,Ogg Vorbis
PS: 实际开发中需要使用音频文件尽量采用 MP3、Ogg 这种有损格式,尽量不要用 WAV、PCM 这种无损音频。
assets文件夹
assets文件夹还有可能放字体文件、预置数据和web页面等
lib库文件夹
只提供对主流架构的支持,比如arm,对于mips和x86架构可以考虑不支持,这样可以大大减小APK的体积。如果是特别大的原生库,我们还可以通过网络,从云端获取,而不直接打包在APK中。native libraries weight reduction
资源混淆方案
-
微信资源混淆方案<code>AndResGuard</code>
AndResGuard是一个帮助你缩小APK大小的工具,他的原理类似Java Proguard,但是只针对资源。他会将原本冗长的资源路径变短,例如将res/drawable/wechat变为r/d/a。
AndResGuard不涉及编译过程,只需输入一个apk(无论签名与否,debug版,release版均可,在处理过程中会直接将原签名删除),可得到一个实现资源混淆后的apk(若在配置文件中输入签名信息,可自动重签名并对齐,得到可直接发布的apk)以及对应资源ID的mapping文件。
美团通过修改aapt来实现资源文件命名的混淆,aapt位于 /sdk/build-tools/{android_version}/ 目录。
网友评论