1. 学习目标
- gradle基础
- 自定义gradle插件
- ASM插桩
2 gradle的概念
Gradle是自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。主要
通过添加一层约定和通过插件预构建的功能,可以轻松构建常见类型的项目
3 构建基础
3.1 gradle 执⾏的⽣命周期
- 初始化阶段
- 执⾏ settings.gradle,确定主 project 和⼦ project
- 解析整个工程中所有的Project,构建所有Project对应的project对象
- 配置阶段
- 执⾏每个 project 的 bulid.gradle,确定出所有 task 所组成的有向⽆环图
- 执行阶段
- 执行具体的task及其依赖的task
- 执行具体的task及其依赖的task
各阶段的生命周期监听
- 初始化阶段:gradle.settingsEvaluated和gradle.projectsLoaded。(在settings.gradle中生效)
- 配置阶段:project.beforeEvaluate和project.afterEvaluate;gradle.beforeProject、gradle.afterProject及gradle.taskGraph.taskGraph.whenReady。
- 执行阶段:gradle.taskGraph.beforeTask和gradle.taskGraph.afterTask
gradle 全局监听
- gradle.addProjectEvaluationListener
- gradle.addBuildListener
- gradle.addListener:TaskExecutionGraphListener (任务执行图监听),TaskExecutionListener(任务执行监听),TaskExecutionListener、TaskActionListener、StandardOutputListener ...
3.2 buildSrc工程
- 特殊的工程,gradle默认编译的工程
- 适合封装为自定义任务或二进制插件
4 插件
4.1插件的类型
- 脚本插件: 通过apply from 引入的.build文件
二进制插件:实现Plugin接口的插件 (主要讲解)
4.2自定义二进制插件
- 创建工程
- 建立buildSrc工程或者子工程
- 定义插件
- 实现Plugin接口
- 注册对于的id
- 实现参数配置
- 定义,注册Extension
- 获取和使用Extension
- 实现功能拓展
- 自定义任务
- 处理文件
- 发布和使用插件
5.字节码插桩
Transform方案的插入时机,在 Class转Dex的过程中修改 Class 字节码。利用 Transform API,我们可以拿到所有参与构建的 Class 文件,然后可以借助ASM 等字节码编辑工具进行修改,插入自定义逻辑。
Instrumentation API 的利用Gradle提供的产物转换API TransformAction,可以注册两个属性间的转换Action,将依赖从一个状态切换到另一个状态
,AGP对其进行了封装,直接AsmClassVisitorFactory便可以进行字节码插桩。
对比TransformAPI方案,InstrumentationAPI方案的优势是
- 不用写复杂的增量构建,内部已经处理了增量逻辑,不需要我们再手动处理
- 构建性能大幅提升,每个transform的操作需要上一次的transofrm操作,新版本只需一次。
新方案让开发更加简洁,并且内置
ASM,所以我们把开发重点放在ASM字节码的操作上 以下是官方的demo
abstract class ExamplePlugin : Plugin<Project> {
override fun apply(project: Project) {
val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
androidComponents.onVariants { variant ->
variant.transformClassesWith(ExampleClassVisitorFactory::class.java,
InstrumentationScope.ALL) {
it.writeToStdout.set(true)
}
variant.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
}
}
interface ExampleParams : InstrumentationParameters {
@get:Input
val writeToStdout: Property<Boolean>
}
abstract class ExampleClassVisitorFactory :
AsmClassVisitorFactory<ExampleParams> {
override fun createClassVisitor(
classContext: ClassContext,
nextClassVisitor: ClassVisitor
): ClassVisitor {
//创建ClassVisitor
return if (parameters.get().writeToStdout.get()) {
TraceClassVisitor(nextClassVisitor, PrintWriter(System.out))
} else {
TraceClassVisitor(nextClassVisitor, PrintWriter(File("trace_out")))
}
}
override fun isInstrumentable(classData: ClassData): Boolean {
return classData.className.startsWith("com.example")
}
}
}
应用场景例子:
- 日志输出
- 方法耗时统计
其他应用:
- 全埋点
- 性能监控
- 防止快速点击
- 第三方库增强或修改