美文网首页
Gradle插件系列(二)—— 配置自己的Transform

Gradle插件系列(二)—— 配置自己的Transform

作者: 一盘好书 | 来源:发表于2021-08-10 15:42 被阅读0次

    在上一篇,我们已经知道了如何创建一个简单的插件,这一节将在此基础上继续说说如何配置自己的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处:对应自定义TransformTask名称,同步完成后,会显示在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,下一节,就来讲讲如果通过更改字节码达到面向切面编程的效果。

    相关文章

      网友评论

          本文标题:Gradle插件系列(二)—— 配置自己的Transform

          本文链接:https://www.haomeiwen.com/subject/zrtfbltx.html