字节码插桩技术,通过AOP的手段实现业务
可以实现的功能:
1.统一处理事件点击,点击防抖
2.日志打点,可以处理自己的activity或者是三方SDK的activity
3.性能监控、动态权限控制等
先看一看android打包过程:
其中需要关注的是中间生成的class文件,通过ASM修改原class文件,生成新的class文件,再使用新的class文件打包到dex文件中;
实现过程
总体思路,遍历项目中所有的.class文件,过滤出需要处理的class文件,在需要处理的方法中,通过ASM插入字节码。
具体实现:
androidstudio使用gradle编译打包项目时,都是通过一个个transform处理的,并且我们可以自定义transform去获取所有class文件的引用,自定义transform需要依赖GradlePlugin,所以首先需要创建一个GradlePlugin;之后再通过ASM插入字节码。
自定义的gradle插件写好后,可以通过gradle构建命令,构建并发布插件,然后就可以在app中使用了
ASM是一套开源框架,常用的几个API如下:
ClassReader,负责解析.class文件中的字节码,并将所有字节码传递给ClassWriter;
ClassVisitor,负责访问class文件中的各个元素,解析class文件结构,然后自动调用内部相应的FieldVisitor或者MethodVisitor方法,进一步解析或者修改class文件内容。
ClassWriter,继承自ClassVisitor,它是生成字节码的工具类,负责将修改后的字节码输出为byte数组。
需要注意的点:
AGP升级到7之后,maven插件不再可用,要换成apply plugin: 'maven-publish'
对应的下面的task也需要换,整体的文件如下
apply plugin: 'groovy'
apply plugin: 'maven-publish'
dependencies {
implementation gradleApi()
implementation localGroovy()
implementation 'com.android.tools.build:gradle:7.1.2'
//ASM相关依赖
implementation 'org.ow2.asm:asm:9.1'
implementation 'org.ow2.asm:asm-commons:9.1'
}
publishing {
publications {
mavenJava(MavenPublication) {
//定义插件的在本地 maven 中的 id
groupId 'danny.lifecycle.plugin'
artifactId 'asm_lifecycle_plugin'
//定义插件的在本地 maven 中的版本号
version '1.0.0'
from components.java
}
}
repositories {
maven {
// 发布位置
url uri('../asm_lifecycle_repo')
}
}
}
实测中发现,Transform类已经废弃,而且使用FileUtils时也找不到,导致demo最终没有成功运行。