Android Gralde插件平台开发系列四:自定义Gradle Transform

本文详细介绍了AndroidGradle插件中的Transform机制,包括Transform的原理、处理流程和开发步骤。Transform作为构建阶段的一个接口,允许开发者在class转dex过程中修改class文件。通过继承Transform类并实现相关方法,可以实现字节码操作,例如进行hook操作。文章还给出了一个简单的Transform实例,展示了如何注册和实现Transform,以及如何遍历和处理jar及directoryInputs。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android Gradle插件平台开发系列:前言

Android Gradle插件平台开发系列一:Android APT

Android Gradle插件平台开发系列二:Android SPI

Android Gradle插件平台开发系列三:自定义gradle plugin

Android Gralde插件平台开发系列四:自定义Gradle Transform

Android Gralde插件平台开发系列五:字节码修改

一、Transform是什么

Gradle Transform是Android官方提供给开发者在项目构建阶段即由class到dex转换期间修改class文件的一套api。

二、Transform原理

每个Transform其实都是一个gradle task,Android编译器中的TaskManager将每个Transform串连起来,第一个Transform接收来自javac编译的结果,以及已经拉取到在本地的第三方依赖(jar、aar),还有resource资源,注意,这里的resource并非android项目中的res资源,而是asset目录下的资源。 这些编译的中间产物,在Transform组成的链条上流动,每个Transform节点可以对class进行处理再传递给下一个Transform。

在这里插入图片描述

三、Transform处理流程

在这里插入图片描述

四、Transform开发流程

4.1 继承Transform类,完成相关抽象方法处理

class TestTransform : Transform() {
    /**
     * 1.Transform名称
     */
    override fun getName(): String {
        return "MyTransform"
    }

    /**
     * 2.Transform要处理的数据类型,即输入文件类型
     *
     * CONTENT_CLASS:表示需要处理 java 的 class 文件。
     * CONTENT_JARS:表示需要处理 java 的 class 与 资源文件。
     * CONTENT_RESOURCES:表示需要处理 java 的资源文件。
     * CONTENT_NATIVE_LIBS:表示需要处理 native 库的代码。
     * CONTENT_DEX:表示需要处理 DEX 文件。
     * CONTENT_DEX_WITH_RESOURCES:表示需要处理 DEX 与 java 的资源文件。
     */
    override fun getInputTypes(): MutableSet<QualifiedContent.ContentType> {
        return TransformManager.CONTENT_CLASS
    }

    /**
     * 3.Transform作用域
     *
     * PROJECT_ONLY:当前工程
     * SCOPE_FULL_PROJECT:所有工程
     */
    override fun getScopes(): MutableSet<in QualifiedContent.Scope> {
        return TransformManager.SCOPE_FULL_PROJECT
    }

    /**
     * 4.是否支持增量编译
     */
    override fun isIncremental(): Boolean {
        return false
    }
}

4.2 重写transform方法,完成jarInputs和directoryInputs拷贝

    /**
     * 5.在这里进行字节码操作
     */
    override fun transform(transformInvocation: TransformInvocation?) {
        super.transform(transformInvocation)
        transformInvocation?.inputs?.forEach {
            // 1.处理jar
            it.jarInputs.forEach {
                // 标准写法,处理完成copy给下一个transform
                val destFile = transformInvocation.outputProvider.getContentLocation(
                    it.name,
                    it.contentTypes,
                    it.scopes,
                    Format.JAR
                )
                FileUtils.copyFile(it.file, destFile)
            }

            // 2.处理directory
            it.directoryInputs.forEach {
                // 标准写法,处理完成copy给下一个transform
                val destDir = transformInvocation.outputProvider.getContentLocation(
                    it.name,
                    it.contentTypes,
                    it.scopes,
                    Format.DIRECTORY
                )
                FileUtils.copyDirectory(it.file, destDir)
            }
        }
    }

4.3 完成字节码处理操作

遍历jarInputs和directoryInputs,找到需要hook的class文件,完成字节码处理操作,字节码处理操作将在下节讲到。

4.3.1遍历jar
    JarFile(it.file).entries().toList().forEach {
        println(it.name)
    }
4.3.2 遍历文件
    FileUtils.getAllFiles(file).filter {
        if (it == null) false else it.name.contains("MainActivity")
    }.forEach {
        // 在这里进行字节码处理
        insertCode(it)
    }

4.4 注册Transform

在上期开发的plugin类里完成Transform注册。

/**
 * 自定义插件
 */
class TestPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        println("==========TestPlugin==========")
        val android = project.extensions.findByType(AppExtension::class.java)
        android?.registerTransform(TestTransform())
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值