Android Gradle7.0 Asm 插件有多简单

648 阅读2分钟

在进入Gradle7.0 后,基于Gradle7.0 自定义的 Plugin 插件,处理 Asm 的代码插桩是非常简单的事情。我们只要关心查找和插桩代码就行了,一句话,把要修改的类找出来,在类对应的方法中 插入业务代码。

例如:我们在开发中,进行log 调试时,需要手动编写log代码,如果这一步骤交给asm就省了很多工作。 先来看看个简单的效果

image.png 在 MainActivity 的 onCreate 、onResume 方法中我们是没有写任何代码的,但是我运行打开app后能在控制台看到日志输出。而且我们知道了MainActivity 会走哪些方法。如下:

image.png

这其实是由我们的插件来完成的。 基于Gradle7.0 ,我们用5分钟来写一个插件看看:

一、构建一个能根据id 来获取 Plugin 的模块

插件可以放在本地,方便修改和调试,有需要可以上传至远程库。

image.png 说明:

  • 1、 插件模块,是一个包含settings.gradle 的一个单独的模块,这里面,你可以创建多个自己想要的插件,其实也就是一个个module

  • 2、定义好一个 DemoPlugin ,继承至 Plugin<Project>

  • 3、定义好一个 ModuleClassVisitorFactory ,继承至 AsmClassVisitorFactory

  • 4、创建 一个 resources , 定义插件由 com.demo.plugin.DemoPlugin 而来,注意插件包名要一致

  • 5、build.gradle 中 ,定义好插件id

  • 6、添加构建到setting.gradle 就可以了

以上都是简单的构建部分:

image.png

gradlePlugin {
    plugins {
        version {
            id = 'com.demo.plugin'
            displayName = 'DemoPlugin'
            description = 'DemoPlugin'
            implementationClass = 'com.demo.plugin.DemoPlugin'
        }
    }
}

二、处理 DemoPlugin

image.png

  • 插件要对应的在 com.android.application 中添加
  • 调用 variant.instrumentationtransformClassesWith 方法添加我们处理class 的 Factory
  • 设置 setAsmFramesComputationMode 模式

三、处理 AsmClassVisitorFactory

image.png

  • AsmClassVisitorFactoryisInstrumentable 方法中,所有class 类都会在这里被扫描到,依据这个,我们可以过滤出对应的 class ,添加到集合里面,返回 true ,即表示要进行代码手术了。

  • createClassVisitorisInstrumentable 方法之后被调用的,在这里进行代码手术,可以自定义一个 ModuleClassVisitor 继承 ClassVisitor

image.png

  • visitCode 方法中, class 类会在这里处理,也是手术的关键。这里 asm 的使用细节暂不多说。

image.png

四、使用 插件

在项目根目录build.gradle下,添加 id 'com.demo.plugin' ,多模块中,哪个模块需要用这个插件,就在他的build.gradle 也添加id 'com.demo.plugin' ,至此,准备工作就完了。

image.png

image.png

最后运行项目,能看到打印,即说明代码插入完成。

image.png

image.png

以上基于Gradle7.0 很快就能入手一个自定义插件,注意在 Gradle7.0 开始,原来的 Transform已经被标记为废弃了。而 Gradle8.0 开始 就不再有 Transform 这个插件

image.png

image.png

有加Log 当然 也有 过滤Log ,过滤 Log 引出了一个问题,那就是过滤了Log 调用后,遗留字符的问题。具体可以参考 字节的这个:

ByteX Log 过滤