【笔记】在 AGP 8 中使用 Transform:ArtifactTransform 与 variant.artifacts.use 的区别与实践

248 阅读2分钟

在 Android Gradle Plugin (AGP) 8.0+ 中,原有的 Transform API 被废弃,取而代之的是更现代的构建管道和组件 API。在开发 Android 插件时,特别是涉及字节码插桩(如 ASM 插码)时,我们常常需要处理 app 本身或第三方依赖(如 SDK)中的 class 文件。

本文对比 ArtifactTransform(也叫 TransformAction)与 variant.artifacts.use(...) 的使用场景和实现方式,避免常见误用和报错。


一、两种处理方式对比

功能处理对象推荐方式
处理 app 自身 class 文件(如插码)当前 module(App 或 Library)variant.artifacts.use(...) + Task
处理 SDK、第三方 AAR/JAR 中的 class 文件所有依赖(包括远程、本地依赖)dependencies.registerTransform(...) + TransformAction

二、处理依赖 class:使用 ArtifactTransform

1. 注册 Transform(推荐写在插件中)

project.dependencies.registerTransform(HookJarTransform::class.java) {
    it.from.attribute(ArtifactAttributes.ARTIFACT_FORMAT, ArtifactType.JAR.type)
    it.to.attribute(ArtifactAttributes.ARTIFACT_FORMAT, "processed-classes-jar")
}

2. 实现 TransformAction

abstract class HookJarTransform : TransformAction<TransformParameters.None> {
    @get:InputFile
    abstract val inputJar: RegularFileProperty

    @get:OutputFile
    abstract val outputJar: RegularFileProperty

    override fun transform(outputs: TransformOutputs) {
        val input = inputJar.get().asFile
        val output = outputJar.get().asFile
        // 用 ASM 插码或复制 class
    }
}

3. 插件类中注册(无需使用 variant.artifacts.use)

class MyPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        project.dependencies.registerTransform(...) // 如上
    }
}

✅ 这种方式适用于你要操作 SDK、依赖 AAR/JAR 包中的 class。


三、处理自身 class:使用 variant.artifacts.use

val transformTask = project.tasks.register("MyClassTransform", MyClassTransformTask::class.java)

androidComponents.onVariants { variant ->
    variant.artifacts.use(transformTask)
        .wiredWithFiles(MyClassTransformTask::inputDir, MyClassTransformTask::outputDir)
        .toTransform(SingleArtifact.ALL_CLASSES_DIRS)
}

这种方式创建 Task 来处理构建产物,适合对当前 module 的 class 文件夹进行插码。

⚠️ 不适用于处理依赖的 AAR 或 JAR!


四、常见错误与解决

错误提示原因正确做法
type mismatch: expected TaskProvider你把 TransformAction 用到了 variant.artifacts.use(...)registerTransform 注册 transform
Could not generate decorated classTransform 参数配置不完整或不可序列化用 Gradle Property<T> 类型,避免非 Serializable 字段
Cannot query propertyGradle Property 没赋值使用 .convention().set() 提前赋默认值

五、总结

  • ✅ 要处理 SDK 依赖里的 class,用 project.dependencies.registerTransform()
  • ✅ 要处理本模块的 class,用 variant.artifacts.use() + Task
  • ❌ 不要在 variant.artifacts.use(...) 中传 TransformAction 类型(会报错)
  • ✅ 插件中也必须区分这两种处理方式