一,寻找优化方向
做优化时,找到优化方向很重要,毕竟任何事情都是先有方向然后再去实践的嘛。
先用 Analyze APK 来分析一下经过数个业务版本迭代过后的Apk
其实网上已经有很多Apk优化的经验了,这里只是因地制宜地明确一下优化目标:
资源优化
图片资源(主要优化res)
资源混淆(主要优化META-INFO/MANIFEST.TF)
arsc文件压缩,通过将aapt编译出来的资源二进制文件resource.arsc中的resource table对应块区的值,修改为混淆后资源路径,从而达到减少字节数的效果。
通过网络下载非必要的本地资源(音频、视频等)。
代码方面(主要优化dex文件)
移除重复引用的第三方库。
移除重复代码块。
基于字节码的dex优化 Proguard And Redex。
是否应该是用7z来对apk进行压缩?
aapt资源打包时,默认不对".jpg", ".jpeg", ".png", ".gif" 这些图片格式的文件进行压缩优化。为了验证,我们使用
aapt l -v xxx.apk
指令来,未经过7z压缩的apk,上述几种图片格式的文件对应的Method都是以Stored
来存储的,根据Zip的文件格式中对压缩方式的描述Compression_methods可以看出这些文件是没有压缩的。所以,我们可以确认,7z进行apk打包,可以带来一定程度上的size优化。
下面会根据上面两个方面的优化进行实战。
二,具体实战
1.1 优化图片资源
使用tinypng、pngquant、ImageOptim啥的图片压缩工具把res/ 下的所有png图片全都进行质量压缩一遍。如果是在Mac下,个人比较推荐用tinypng(有损压缩)压一遍之后,再用ImageOptim(无损压缩)压一遍,这样可以达到比较大的压缩效果。
1.2 & 1.3 资源混淆 & arsc文件压缩
这里使用到了微信的一个开源框架AndResGuard,这个框架的原理类似Java Proguard,但是只针对资源。他会将原本冗长的资源路径变短,例如将
res/drawable/wechat
变为r/d/a
。这会极大程度的保护我们的资源,同时也会带来一些优化效果。
将AndResGuard引入项目需要注意的问题
compress
参数对安装包体积影响很大。若要支持2.2,resources.arsc需保证压缩前小于1M。keepmapping方式对增量包大小的影响影响并不大,但使用keepmapping方式有利于保持所有版本混淆的一致性。
白名单的添加:1、若想通过getIdentifier方式获得资源,需要放置白名单中。(通过R.java的引用方式来获取资源,尽量不要直接使用getIdentifier方式获取资源,因 为这样会带来 Lint等工具的引用检测失效 等问题。)2、部分手机桌面快捷图标的实现有问题,务必将程序桌面icon加入白名单3、第三方库有某些资源不能混淆,否则会crash,详细请参考
是否与多渠道打包产生互相影响?(因为涉及到使用7z的方式来重打包apk,所以这一步是需要考虑的)
因为resources.arsc 在 APK 安装之后仍需要被频繁的读取,进行压缩后可能会带来一些内存使用的上升。
2. 优化代码
使用
./gradlew dependencies
命令能够很清晰的看到项目依赖情况(项目依赖太多我就不贴出来了),可以很容地筛选重复依赖。使用Android Studio的Inspector,去检测无用代码块,引用,定义 等等。
基于字节码的优化
Android目前基于字节码的优化有两种方案。
ProGuard
Proguard本身就已经做了不错的代码优化,它的好处不再多说,但是推荐一个开源项目
Facebook推出的一款优化字节码的库,在项目上做了实现,在使用了Proguard,再使用Redex进行dex压缩,发现两个dex各小了0.1M,但浏览了一下issue,看到一些奇怪的安装失败的case,由于效果不太大,且这个库不是很成熟,所以没引入。
三,最后
随着项目业务不断增多,参与开发人员也不断变多,不同的编码习惯和水平也许会带来一些技术债务和线上隐患,一些代码规范如果能够做起来,也许能够在程序员开发阶段将这些债务消化掉。
使用CheckStyle或者Lint自定义规则,在开发阶段使用工具进行代码规范检测。
使用git-precommit,在代码提交阶段,对commit的资源进行引用检测、对代码进行质量检测