什么是 Plugin Transform?
Transform 是 Android Gradle plugin团队提供给开发者使用的一个抽象类, 从1.5.0-beta1 版本开始提供了 Transform API
com.android.build.api.transform.Transform
它能干啥?
提供接口让开发者可以在源文件编译成为 class 文件之后,dex 之前进行字节码层面的修改。借助 javaassist,ASM 这样的字节码处理工具,可以通过自定义 Gradle 插件来注册自定义的 Transform,在自定义的 Transform 中进行代码的插入,修改,替换,甚至是新建类与方法,注册后 Transform 会包装成一个 Gradle Task 任务,这个 Task 在 compile task 执行完毕后运行。
记住两个核心的API: TransformInput
和 TransformOutputProvider
;
- TransformInput
TransformInput
代表的是输入文件抽象接口,获取DirectoryInput
集合和获取JarInput
集合,DirectoryInput
是以 源码 方式参与项目编译所有目录结构及其目录下的源文件;而JarInput
是以 jar 包方式参与项目编译的所有 jar 包和远程包。
package com.android.build.api.transform;
import com.android.annotations.NonNull;
import java.util.Collection;
public interface TransformInput {
/**
* Returns a collection of {@link JarInput}.
*/
@NonNull
Collection<JarInput> getJarInputs();
/**
* Returns a collection of {@link DirectoryInput}.
*/
@NonNull
Collection<DirectoryInput> getDirectoryInputs();
}
- TransformOutputProvider
代表的是输出文件抽象接口,重点关注
getContentLocation(...)
方法
1,name 代表该 Transform 对应的 Task 的名称
2, QualifiedContent.ContentType 需要处理的数据类型,CLASSES
代表 需要处理编译后的字节码,可能是jar
也可能是 目录。RESOURCES
代表处理标准的 java 资源
3,scopes
也是一个比较有意思的枚举类,PROJECT
只处理当前项目,SUB_PROJECTS
只处理子项目,PROJECT_LOCALDEPS
只处理当前项目的本地依赖,例如:jar
,arr
。SUB_PROJECTS_LOCAL_OEPS
只处理子项目的本地依赖。例如:jar
,arr
,EXTERNAL_LIBRARIES
只处理外包的依赖库,PROVIDED_ONLY
只处理本地或远程以provided
形式引入的依赖库。而TESTED_CODE
指的是测试代码。
package com.android.build.api.transform;
import com.android.annotations.NonNull;
import java.io.File;
import java.io.IOException;
import java.util.Set;
public interface TransformOutputProvider {
void deleteAll() throws IOException;
@NonNull
File getContentLocation(
@NonNull String name,
@NonNull Set<QualifiedContent.ContentType> types,
@NonNull Set<? super QualifiedContent.Scope> scopes,
@NonNull Format format);
}
public interface QualifiedContent {
enum DefaultContentType implements ContentType {
/**
* The content is compiled Java code. This can be in a Jar file or in a folder. If
* in a folder, it is expected to in sub-folders matching package names.
*/
CLASSES(0x01),
/** The content is standard Java resources. */
RESOURCES(0x02);
private final int value;
DefaultContentType(int value) {
this.value = value;
}
@Override
public int getValue() {
return value;
}
}
enum Scope implements ScopeType {
/** Only the project (module) content */
PROJECT(0x01),
/** Only the sub-projects (other modules) */
SUB_PROJECTS(0x04),
/** Only the external libraries */
EXTERNAL_LIBRARIES(0x10),
/** Code that is being tested by the current variant, including dependencies */
TESTED_CODE(0x20),
/** Local or remote dependencies that are provided-only */
PROVIDED_ONLY(0x40),
/**
* Only the project's local dependencies (local jars)
*
* @deprecated local dependencies are now processed as {@link #EXTERNAL_LIBRARIES}
*/
@Deprecated
PROJECT_LOCAL_DEPS(0x02),
/**
* Only the sub-projects's local dependencies (local jars).
*
* @deprecated local dependencies are now processed as {@link #EXTERNAL_LIBRARIES}
*/
@Deprecated
SUB_PROJECTS_LOCAL_DEPS(0x08);
private final int value;
Scope(int value) {
this.value = value;
}
@Override
public int getValue() {
return value;
}
}
}
网友评论