写给 Android 开发者的 Gradle 系列(四)plugin 实战包体积瘦身

本文介绍了一种通过自定义Gradle插件减少Android应用APK体积的方法。通过分析R文件的字段,删除冗余常量并替换引用,插件可以在混淆后进一步优化包大小。文章详细讲解了插件的实现过程,包括如何在混淆任务后操作.class文件,以及如何使用ASM库修改字节码。实验证明,该插件可以显著降低包含大量资源的项目的APK大小。
摘要由CSDN通过智能技术生成

如果你对本文感兴趣,也许你对我的公众号也会有兴趣,可扫下方二维码或搜索公众微信号:mxszgg

本文由玉刚说写作平台提供写作赞助,版权归玉刚说微信公众号所有

原作者:joker

版权声明:未经玉刚说许可,不得以任何形式转载

本文插件基于 Android Gradle Plugin 3.0.1 版本

前言

日常开发中,为了避免运行时 R 文件反射失败,一般在混淆的时候都会将 R 文件 keep 住,但是因此也会导致包体积有一定的上升,那么有没有减少 R 文件未混淆带来的体积增长呢?

众所周知,Android 中的 R 文件用来存储资源的映射值,而往往一个 apk 中的 R 文件中的字段值的数量是十分庞大的,笔者将一个未进行任何操作的 debug apk 进行解压后发现该文件行数就已超过 1800 行——

为了减少包体积,可以将混淆压缩的话,可以降到500行+左右——

但是混淆后就会存在两个问题——R 文件被混淆了之后,那么资源反射就不能使用了;混淆过程中删除了除 R$styleable.class 以外的其他的 R$*.class,但是 R$styleable.class 仍然是可以优化的。那么该如何解决这两个问题呢?一个方案是不开启混淆,这显然不太现实;另一个方案是开启混淆,同时在 proguard-rules.pro 中 keep 住 R 文件,再手动删除 R 文件中的字段信息。实际上美丽说团队早期已经开源过一个 thinrPlugin 就是使用方案二,但其针对的是 Gradle plugin 1.0/2.0 的版本,并未对 3.0 做支持,本文将重写该插件,并命名为 thinr3。

写插件前笔者谈及一点前提知识以及插件思路——为什么 R 文件中的字段可以删除?R 文件中的字段分为两种类型,一种是 static final int,另一种是 static final int[]。其中,static final int 作为常量在运行时是不会被改变的,那么将这些常量打进 apk 中很明显是多余的,所以实际上打包进 apk 的 R 文件有很大一部分是冗余的

例如上图中的 R.layout.activity 是完全可以被其所对应的常量替换的,但是由于 keep 住了 R 文件,所以它不会进行替换。

thinr3 的思想就是找到使用 R 字段的地方,如果该字段是常量则将其替换成这个常量所对应的值,并删除 R 文件中该字段,去除冗余——

插件的运行需要对 .class 文件分两次遍历,第一次遍历先是获取到 R.class 文件,遍历其中所有的常量值,封装成键值对用以后面将字段替换成相应的常量;第二次遍历分两种情况,如果是 R 文件那么则将其常量进行删除,如果是其他 .class 文件,则将当中的 R 字段引用根据前面的键值对进行替换。为了对 .class 文件进行操作,需要引入 ASM,不了解 ASM 没有关系,本文阐述的插件中运用到 ASM 的部分不多。

那么由此可知,何时何地获取 .class 文件实际上就是整个 task 的核心所在——理论上越靠后 .class 文件将会被修改的风险就越小,笔者选择了在混淆 task (transformClassesAndResourcesWithProguardFor${variant.name.capitalize()})执行之后启用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值