背景:
Google的AGP 8.0 已经出来一段时间了,基于8.0有许多新的特性,比如baseline profile,dexlayout等,这些特性可以大幅度的提升app的启动速度。相信大家都很心动吧。但是要用上如此的属性,必现要AGP 8.0才可以。而AGP 8.0升级最大的一个问题就是,针对历史版本的TransfromManager,被废弃掉了。各家大厂的APP,多多少少都会通过ASM字节码注入框架,实现一些内容.比如Router,方法耗时收集,日志收集等。下面我们就对transform的适配,进行详细的讲解。
适配方案:
Transfrom的适配方案大的方便可以分为两种情况:
第一种是直接通过扩展Gradle提供的TransfromAction来实现,该实现需要自己定义transfrom转化过程中的各个属性的变化。具体实现参考官方的文档: Transforming dependency artifacts on resolution;
第二种实现是AGP提供的,基于Gradle之上,封装好的api和类的实现。没有直接可供替换的api和类,而是需要根据不同的使用场景,进行不同的适配。所有替代api都在androidComponents {}里。
下面我们主要介绍AGP提供的Variant API的实现。该实现也分两种情况,针对不同的场景,提供了不同的实现。第一种是。第二种适配方案,是针对需要直接处理全部输入classes的情况,官方提供了 针对历史的Transfrom所支持的功能,主要分为两类:
第一种是直接字节码插装,比如方法耗时,日志注入。可以直接基于AsmClassVisitorFactory的自定义实现,来直接进行字节码处理。
第二种是针对需要先全局遍历所有的字节码,找到对应类,方法,相关的数据,然后二次遍历,进行插装。可以基于AGP提供的如下api进行实现:
variant.artifacts.forScope(ScopedArtifacts.Scope.ALL) .use(taskProvider) .toTransform( ScopedArtifact.CLASSES, ModifyClassesTask::allJars, ModifyClassesTask::allDirectories, ModifyClassesTask::output, )
针对上面两种方案的具体实现,可以参考如下的案例:
字节码直接插装的适配方案如下:
案例说明:
该案例实现如下功能:收集线上代码类的使用情况,从而通过数据分析,针对线上未使用的类,进行移除,而从缩减包体积。下面插件就是针对apk里面类使用情况的一个数据收集插件。
直接插装字节码-kotlin实现:apply插件的实现:
class AsmTransformFactoryPlugin : Plugin<Project> {
override fun apply(target: Project) {
val customPluginConfig = target.extensions.create("excludeClassWhiteList", CollectUsageExtension::class.java)
val androidComponents = target.extensions.getByType(AndroidComponentsExtension::class.java)
androidComponents.onVariants { variant ->
variant.instrumentation.transf