Gradle Transform的定义过程

962 阅读3分钟

1:新建项目

2:创建一个AndroidLibraryModule,取名为plugin

3:清空plugin/build.gradle内容修改成如下:

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

dependencies{
    compile gradleApi()
    compile localGroovy()
    compile 'com.android.tools.build:gradle:3.2.1'
}
repositories{
    jcenter()
}

uploadArchives{
    repositories.mavenDeployer{
        //本地仓库路径,这里是放到项目根目录下的repo文件夹
        repository(url:uri('../repo'))
        //下面这三行则是定义生成依赖包的名称为com.mwy.learn:autotrack.android:1.0.0
        //这个主要是在项目根目录的build.gradle文件中引用的样式(classpath'com.mwy.learn:autotrack.android:1.0.0')
       //groupId为组织或公司名称,artifactId为项目名或者模块儿名,version为项目或模块的当前版本号
        pom.groupId='com.mwy.learn'
        pom.artifactId='autotrack.android'
        pom.version='1.0.0'
    }
}

4:删除plugin/src/mian下的所有文件,并新建groovy目录,在该目录下创建一个包(com.mwy.learn.transform)

5:创建Transform类:在上面的包中创建一个transform类,但是必须以.groovy结尾(LearnTransform.groovy)

具体代码为:

class LearnTransform extends Transform {
    private static Project project

    LearnTransform(Project project) {
        this.project = project
    }
/**
 * 对应该transform对应的task的名称
 * 它会在app/build/intermediates/transforms目录下
 * @return
 */
    @Override
    String getName() {
        return "LearnTransform"
    }
/**
 * 指定transform要处理的数据类型
 * 主要有两种:CLASSES(要处理编译后的字节码,可能是jar也可能是目录)和RESOURCES(处理标准的Java资源)
 * @return
 */
    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }
/**
 * 指定transform作用域有以下7种
 * 1:PROJECT(只处理当前项目)2:SUB_PROJECTS(只处理子项目)3:PROJECT_LOCAL_DEPS(只处理当前项目的本地依赖如jar、aar)
 * 4:SUB_PROJECTS_LOCAL_DEPS(只处理子项目的本地依赖如jar、aar)5:EXTERNAL_LIBRARIES(只处理外部的依赖库)
 * 6:PROVIDED_ONLY(只处理本地或者远程以provided形式引入的依赖库)7:TESTED_CODE(测试代码)
 * @return
 */
    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT
    }
/**
 * 是否是增量构建
 * @return
 */
    @Override
    boolean isIncremental() {
        return false
    }

    static void printCopyRight() {
        println()
        println("###################################### ")
        println("#######                         ###### ")
        println("#######                         ###### ")
        println("#######  这是一个测试编译的插件例子  ###### ")
        println("########      不知道好不好使       ###### ")
        println("#######                         ###### ")
        println("#######                         ###### ")
        println("##################################### ")
        println()
    }

    @Override
    void transform(Context context, Collection<TransformInput> inputs, Collection<TransformInput> referencedInputs, TransformOutputProvider outputProvider, boolean isIncremental) throws IOException, TransformException, InterruptedException {
        printCopyRight()
        //transform的inputs有两种类型,一种是目录,一种是jar包,分开遍历
        inputs.each { TransformInput input ->
            //遍历目录
            input.directoryInputs.each { DirectoryInput directoryInput ->
                //获取output目录
                def dest = outputProvider.getContentLocation(directoryInput.name, directoryInput.contentTypes, directoryInput.scopes, Format.DIRECTORY)
                //将input目录复制到output指定目录
                FileUtils.copyDirectory(directoryInput.file, dest)
            }
            input.jarInputs.each {JarInput jarInput->
                //重命名输出文件(同目录copyFile会冲突)
                def jarName = jarInput.name
                def md5Name = DigestUtils.md5Hex(jarInput.file.getAbsolutePath())
                if (jarName.endsWith(".jar")) {
                    jarName = jarName.substring(0,jarName.length()-4)
                }
                File copyJarFile = jarInput.file
                def dest = outputProvider.getContentLocation(jarName+md5Name,jarInput.contentTypes,jarInput.scopes,Format.JAR)
                FileUtils.copyFile(copyJarFile,dest)

            }
        }
    }
}

这里的getName在studio中的展示如下

这里面的transform其实什么也没做,就仅仅是将输入文件拷贝到输出文件下,然后什么都没做,但是这个操作不可省略。一旦省略也就是transform方法空实现,最后会导致打包的apk缺少.class文件。

6.创建Plugin:与transform同目录下创建一个plugin类(LearnTransformPlugin.groovy),主要是将自定义的transform应用到工程中

public class LearnTransformPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {

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

7:创建properties文件:在/plugin/src/main/目录下新建目录resources/META-INF/gradle-plugins,然后在此目录中创建问价com.mwy.transform.properties。其中.properties之前的这个文件名就是将来在引用模块中的build.gradle中引用的名字(apply plugin: 'com.mwy.transform')该文件的内容就一行,定义plugin文件的全路径

implementation-class=com.mwy.learn.transform.LearnTransformPlugin

8:生成依赖:就是执行uploadArchive构建plugin。点击studio的右侧gradle栏,点击uploadArchives构建任务,完成之后会在项目的根目录下生成构建好的包。

9:添加依赖:在项目的根目录下的build.gradle文件中buildScript-repositories中添加本地maven依赖,并且在dependencies中添加自定义的构建工具,完整代码如下:

buildscript {
    
    repositories {
        google()
        jcenter()
        //添加本地依赖
        maven{
            url uri('repo')
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        //添加构建工具
        classpath'com.mwy.learn:autotrack.android:1.0.0'

    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

在app/build.gradle中引用插件即可。apply plugin: 'com.mwy.transform' 接着可以直接打包运行app就可以看到打印出来的log