android aar项目_Android 编译插桩(二): Gradle Transform

75f4287098dc6825d61d70e43cdd4253.png

Android 编译插桩(二): Gradle Transform

Android 的打包流程

2de12d7f085557fbaab56bbed82a2c3a.png

上图是 apk 打包的流程,可以看启用有一步是 .class 文件到 .dex 发文件的转换。而 Gradle Transform 是 Android 官方提供的在这一阶段用来修改 .class 文件的一套标准 API。 这一应用现在主要集中在字节码查找、代码注入等

1. Transform 原理

7386a64c4ce27183420413a0b855c886.png

图片出自 https://cloud.tencent.com/developer/article/1378925

每个 Transform 都是一个 gradle task, 将 class 文件、本地依赖的 jar, aar 和 resource 资源统一处理。

每个 Transform 在处理完之后交给下一个 Transform。如果是用户自定义的 Transform 会插在队列的最前面。

1.1 Transform 主要方法

Transform 是一个抽象类

public 

1.2 TransformInput 输出

TransformInput 是指这些输入文件的一个抽象,包含两个部分

  • DirectoryInput 集合 是指以源代码方式参与项目编译的所有目录结构及其目录下的源代码
  • JarInput 集合 是指以 jar 包方式参与项目编译的本地 jar 包和远程 jar 包,包含 aar

输出是在 transform 方法里面处理

void 

1.3 Transform 的使用

创建的目录结构

862424ee32a1c78f898798088da1d9e3.png

第一步,创建 Android Library module, 修改 gradle 的内容

apply plugin: 'groovy'
apply plugin: 'maven'

dependencies {
    implementation gradleApi()
    implementation localGroovy()

    compileOnly 'com.android.tools.build:gradle:3.4.1'
}

repositories {
    jcenter()
}

// 上传到本地的代码仓
uploadArchives{
    repositories.mavenDeployer{
        // 本地仓库路径
        repository(url: uri('../repo'))

        // 设置 groupId 
        pom.groupId = 'com.yxhuang'

        // 设置 artifactId
        pom.artifactId = 'autotrack.android'

        // 设置 插件版本号
        pom.version = '1.0.0'
    }
}

第二步,新进 groovy 目录,创建 Transform 类

class AnalyticsTransform extends Transform {

    @Override
    String getName() {
        return "AnalyticsAutoTrack"
    }

    /**
     * 需要处理的数据
     * @return
     */
    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }

    /**
     *  Transform 要操作的内容范围
     * @return
     */
    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT
    }

    @Override
    boolean isIncremental() {
        return false
    }

    @Override
    void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
        customTransform(transformInvocation.getContext(), transformInvocation.getInputs(),
                transformInvocation.getOutputProvider(), transformInvocation.incremental)
    }

    void customTransform(Context context, Collection<TransformInput> inputs, TransformOutputProvider outputProvider,
                         boolean isIncremental) {

        if (!isIncremental) {
            outputProvider.deleteAll()
        }
        // 遍历
        inputs.forEach { TransformInput input ->

            // 遍历目录
            input.directoryInputs.each { DirectoryInput directoryInput ->
                handleDirectoryInputs(directoryInput)
            }

            // 遍历 jar
            input.jarInputs.each { JarInput jarInput ->
                handleJarInputs(jarInput)
            }
        }
    }

第三步创建 plugin, 注册 transform

// AnalyticsPlugin.groovy
class AnalyticsPlugin implements Plugin<Project>{

    @Override
    void apply(Project project) {
        // ‘analytics’ 在 build.gradle 中传值使用
        AnalyticsExtension extension = project.extensions.create("analytics", AnalyticsExtension)
        println("------------AnalyticsPlugin apply  extension disableAutoTrack --------------" +  extension.disableAutoTrack)

        AppExtension appExtension = project.extensions.findByType(AppExtension.class)
        appExtension.registerTransform(new AnalyticsTransform(extension))
    }
}

其中 AnalyticsExtension 是自定义属性类,可以通过主项目的 build.gradle 文件传值

/**
 * 定义额外的属性
 */
class AnalyticsExtension {

    /**
     * 是否禁止自动插桩
     */
    boolean disableAutoTrack = false
}

主项目的 build.gradle 命名的 scope 要与注册时的一致,例如下的 analytics

// 与 AsmPlugin 中创建 project.extensions.create("analytics", AnalyticsExtension) 创建是要一致
analytics {
    disableAutoTrack = false
}

第四步 创建 properties 文件 在 plugin/src/main 目录下创建新目录 resources/META-INFO/gradle-plguins, 然后创建文件,内容指定为上一步创建的 plugin

implementation-class=com.yxhuang.analytics.android.plugin.AnalyticsPlugin

第五步,修改相关的 build.gradle 文件,添加依赖 在根项目的 build.gradle 中添加

5d81c0d54a9d630cfc582bb2d54a6b9d.png

在 asm/build.gradle 中添加

d6a7ddb39e87067a3df4ad5f81ba6882.png

最后是构建 在 gradle task 里面,运行 uploadArchives 任务即可

db8f563aa28901a8990a82f359500ac8.png

参考

  • 一起玩转Android项目中的字节码(Transform篇)
  • 王灼洲 ·《Android 全埋点解决方案》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值