Android Transform API

上一章知道如何自定义 Gradle插件后,我们到底可以用来做什么呢?难道只是用来定义一些简单的 Task?本章给你答案!

什么是 Transform API

Android Gradle 工具从 1.5.0-beta1 版本开始,包含了 Transform API,它允许第三方插件在将编译后的类文件转换为 dex 文件之前对 .class 文件进行操作。

Transform 的工作原理

接下来看下它的工作原理:

Android Transform API

  • 很明显它是一个链式结构,每个 Transform 都是一个 Gradle 的 Task,Android 编译器通过 TaskManager 将每个 Transform 串联起来。
  • 第一个 Transform 接收 javac 编译的结果,以及 jar 包依赖和 resource 资源,这些编译的中间产物在 Transform 链上流动。其中,我们自定义的 Transform 会插入到最前面

Transform API 的使用

Transform API 其实就是继承自 Transform 写一个实现类,我们看下 Transform 需要实现的方法:

Android Transform API

简单介绍下这几个方法:

getName():用于指定 Transform 的名字,对应了该 Transform 所代表的 Task 的名称,例如:

Android Transform API

isIncremental():方法指明是否支持增量编译。

getInputTypes():用于指定 Transform 的输入类型,可以作为输入过滤的一种手段。在 TransformManager 中定义了很多类型:

  • CONTENT_CLASS // 代表 javac 编译成的 class 文件(一般用它)
  • CONTENT_JARS
  • CONTENT_RESOURCES // 这里的 resources 单指 java 的资源
  • CONTENT_NATIVE_LIBS
  • CONTENT_DEX
  • CONTENT_DEX_WITH_RESOURCES
  • DATA_BINDING_BASE_CLASS_LOG_ARTIFACT

getScopes():用于指定 Transform 的作用域。同样在 TransformManager 中定义了很多类型,常用的是 SCOPE_FULL_PROJECT,即代表所有 Project。

确定了 ContentType 和 Scope 后就确定了该自定义 Transform 需要处理的资源流。
例如,上面提到的常用输入类型(CONTENT_CLASS)和常用作用域(SCOPE_FULL_PROJECT)表示的就是 所有项目中 java 编译成的 class 组成的资源流

接下来我们来看需要复写的核心方法:

Android Transform API

TransformInvocation 接口定义如下:

Android Transform API

看下 TransformInput 的接口定义:

所谓 Transform 就是对输入的 class 文件转变成目标字节码文件,TransformInput 就是这些输入文件的抽象。目前它包括两部分:DirectoryInput 集合与 JarInput 集合。

Android Transform API

TransformOutputProvider 通过调用 getContentLocation 来获取输出目录:

Android Transform API

复写完 Transform 的核心方法之后,我们需要通过插件注册它才可使用:

Android Transform API

整体看下 CustomTransform 类:

Android Transform API

接下来看下读取 class 文件的流程:

Android Transform API

Demo 工程

Android 工程:https://github.com/changer0/ASMInjectDemo

以上就是本节内容,欢迎大家关注????????????

Android Transform API