一个基于 Android Gradle Plugin 的字节码转换框架,核心代码修改自 booster,将常用功能整合到一起,并额外支持通过 SPI(Service Provider Interface)机制配置插件和替换 JAR 中的类。
plugin-extensions/
├── core/ # 核心模块,包含插件主体逻辑
├── core-extensions/ # 核心扩展模块,包含注解定义
├── plugin-demo/ # 示例插件模块
└── plugin-trace/ # 方法耗时统计插件模块
- 字节码转换:基于 ASM 实现的字节码转换能力
- SPI 机制:通过
META-INF/services自动发现和加载插件组件 - 配置扩展:支持自定义 Gradle DSL 配置
- JAR 类替换:支持替换第三方 JAR 包中的类
- Variant 处理:支持 Android Variant 级别的处理
在项目的 build.gradle.kts 中应用插件:
plugins {
id("com.jiaoay.plugins")
}extensionsPlugin {
isEnableSdkPatcher = true
replaceClassMap = mutableMapOf(
"some-library.jar" to mutableListOf(
"com/example/TargetClass.class"
)
)
}创建一个实现 Transformer 接口的类:
class MyTransformer : Transformer {
override fun onPreTransform(context: TransformContext) {
// 转换前的准备工作
}
override fun transform(context: TransformContext, bytecode: ByteArray): ByteArray {
// 使用 ASM 进行字节码转换
val classReader = ClassReader(bytecode)
val classWriter = ClassWriter(ClassWriter.COMPUTE_MAXS)
// ... 转换逻辑
return classWriter.toByteArray()
}
override fun onPostTransform(context: TransformContext) {
// 转换后的清理工作
}
}在 src/main/resources/META-INF/services/com.jiaoay.plugins.core.transform.Transformer 文件中注册:
com.example.MyTransformer
open class MyConfig {
companion object {
const val NAME = "myPlugin"
fun get(project: Project): MyConfig {
return project.extensions.getByName(NAME) as? MyConfig ?: MyConfig()
}
}
var isEnable: Boolean = false
}class MyConfigImpl : PluginConfig {
override fun getConfigClass(): Class<*> = MyConfig::class.java
override fun getConfigName(): String = MyConfig.NAME
}在 src/main/resources/META-INF/services/com.jiaoay.plugins.core.config.PluginConfig 文件中注册:
com.example.MyConfigImpl
在 build.gradle.kts 中即可使用自定义 DSL:
myPlugin {
isEnable = true
}方法耗时统计插件,用于在方法前后插入耗时统计代码。
配置示例:
pluginTrace {
isEnable = true
traceWhiteSet = mutableSetOf("com.example.app") // 白名单,匹配的包名会被插桩
traceBlackSet = mutableSetOf("com.example.app.excluded") // 黑名单,匹配的包名会被过滤
}在代码中使用 @Trace 注解可以标记需要统计耗时的类。
演示插件,展示如何实现一个基本的 Transformer。
用于标记需要替换的类:
@SdkPatcher(name = "TargetClassName")
class MyPatchClass {
// 替换目标类的实现
}用于标记需要进行方法耗时统计的类:
@Trace
class MyActivity : Activity() {
// 该类的方法会被自动插入耗时统计代码
}Apache License 2.0