在上一篇,我们已经知道了如何创建一个简单的插件,这一节将在此基础上继续说说如何配置自己的Transform
。
1 转换器 Transform
转换器Transform
是由Google
提供,让开发者可以在编译后,打包前这段时期,进行额外干预操作,从而提供操作字节码的时机。
2 创建 Transform
创建自定义的FreeCoderTransform
类,然后继承至Transform
。
public class FreeCoderTransform extends Transform {
// 1
@Override
public String getName() {
return "freecoder";
}
// 2
@Override
public Set<QualifiedContent.ContentType> getInputTypes() {
return TransformManager.CONTENT_CLASS;
}
// 3
@Override
public Set<? super QualifiedContent.Scope> getScopes() {
return TransformManager.SCOPE_FULL_PROJECT;
}
// 4
@Override
public boolean isIncremental() {
return false;
}
// 5
@Override
public void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
Collection<TransformInput> inputs = transformInvocation.getInputs();
TransformOutputProvider outputProvider = transformInvocation.getOutputProvider();
inputs.forEach(transformInput -> {
transformInput.getJarInputs().forEach(jarInput -> {
File dest = outputProvider.getContentLocation(jarInput.getName(), jarInput.getContentTypes(), jarInput.getScopes(), Format.JAR);
try {
FileUtils.copyFile(jarInput.getFile(), dest);
} catch (IOException e) {
e.printStackTrace();
}
});
transformInput.getDirectoryInputs().forEach(directoryInput -> {
File dest = outputProvider.getContentLocation(directoryInput.getName(), directoryInput.getContentTypes(), directoryInput.getScopes(), Format.DIRECTORY);
try {
FileUtils.copyFile(directoryInput.getFile(), dest);
} catch (IOException e) {
e.printStackTrace();
}
});
});
}
}
标记1处:对应自定义Transform
的Task
名称,同步完成后,会显示在Gradle
控制面板上,比如:transformClassesWithXXXForDebug
。
标记2、3处:定义了我们将要操作的编译过程中具体哪些类型的文件,其中 2 的类型:
CONTENT_CLASS://class 文件
CONTENT_JARS: //jar包,包括class文件与resource资源文件
CONTENT_RESOURCES // resource资源文件
CONTENT_NATIVE_LIBS // 本地libs
CONTENT_DEX // dex文件
CONTENT_DEX_WITH_RESOURCES // dex文件与resource资源文件
标记 3 处:表示作用的项目范围,SCOPE_FULL_PROJECT
表示整个项目。
标记 4 处:表示是否支持增量编译。
标记 5 处:这里是个核心方法,需要覆盖重写,并且按Google
提供的输出目录outputProvider
上输出,否则将这个Transform
引入会报错。
transformInvocation.getInputs()
获取编译后的所有class
文件,transformInvocation.getOutputProvider()
获取Google
提供的输出目录,我们把这些编译后的文件做完处理后,然后再扔向该目录,最终参与到打dex
包的过程。
而后就是简单的复制工作,至于处理,我们下一节讲,这个过程可以实现面向切面的编程。
3 引入 Transform
如下:(接上一节代码)
public class FreeCoderPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
final FreeCoderExtension extension = project.getExtensions()
.create("freecoder", FreeCoderExtension.class);
project.afterEvaluate(innerProject -> System.out.println("extension: " + extension.name));
// 创建转换器
FreeCoderTransform freeCoder = new FreeCoderTransform();
// 1
BaseExtension baseExtension = project.getExtensions().getByType(BaseExtension.class);
// 2
baseExtension.registerTransform(freeCoder);
}
}
标记1处:BaseExtension
指的就是Android打包过程中,com.android.application
这个插件所包含的扩展,方便开发者在打包过程中进行相应的干预。
标记2处:把我们的Transform
注册进入该扩展中。
到此为止,我们就配置好了自己的Transform
,下一节,就来讲讲如果通过更改字节码达到面向切面编程的效果。