您的当前位置:首页正文

学习自定义Gradle插件

来源:花图问答

自定义 Gradle 插件

  1. 首先新建一个项目
  2. 新建一个module模块,删除无关文件,只需保留main和build.gradle文件即可
  3. gradle文件中删除之前默认所有配置,引入如下配置
//管理仓库的插件
apply plugin: 'maven'
//groovy插件
apply plugin:'groovy'

dependencies {
    compile gradleApi()
    compile localGroovy()
}

  1. 在main目录下新建groovy和main文件夹
  2. 在groovy文件夹下建包,写对应的插件
package com.okay.plugin

import org.gradle.api.Plugin
import org.gradle.api.Project

public class LifeCyclePlugin implements Plugin<Project>{

    @Override
    void apply(Project project) {
        System.out.println("== LifeCyclePlugin Plugin gradle plugin ==")
    }
}
  1. 在gradle中配置插件版本和仓库信息
group = 'com.okay.plugin'
version = '1.0.0'

uploadArchives{
    repositories{
        mavenDeployer{
            //本地maven地址
            repository(url : uri('../asm_lifecycle_repo'))
        }
    }
}

7.在plugin/src/main目录下新建目录resources/META-INF/gradle-plguins,然后在此目录下新建一个文件zyl.asm.lifecycle.properties。(zyl.asm.lifecycle是插件名称)

implementation-class= com.okay.plugin.LifeCyclePlugin

8.生成插件
现在可以在 Android Studio 的右边栏找到 Gradle 中Tasks/upload下找到并点击 uploadArchives,执行 plugin 的部署任务。就会生成asm_lifecycle_repo文件夹

测试插件

  1. 在app的build.gradle文件中添加插件配置
apply plugin: 'com.android.application'
apply plugin: 'zyl.asm.lifecycle'

buildscript {
    repositories {
        //自定义插件的maven地址
        maven {url '../asm_lifecycle_repo'}
    }

    dependencies {
        //加载自定义插件 group+module+version
        classpath 'com.okay.plugin:asm_lifecycle_pulgin:1.0.0'
    }
}

2.在studio的Terminal控制台输入./gradlew clean assembledebug命令,控制台输出

> Configure project :app
== LifeCyclePlugin Plugin gradle plugin ==

BUILD SUCCESSFUL in 22s

打印了我们的日志,说明插件生效了。

自定义Transform,实现遍历.class文件

  1. 在gradle插件的基础上,添加依赖
apply plugin: 'maven'
apply plugin:'groovy'

dependencies {
    compile gradleApi()
    compile localGroovy()
    //添加gradle库
    compile 'com.android.tools.build:gradle:3.6.2'
}
...
  1. 在grovvy文件夹下新建新建LifeCycleTransform.groovy,并继承 Transform 抽象类。
package com.okay.plugin

import com.android.build.api.transform.DirectoryInput
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformException
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.internal.pipeline.TransformManager
import groovy.io.FileType

public class LifeCycleTransform extends Transform{

    /**
     * 设置我们自定义的Transform对应的Task名称。Gradle在编译的时候,会将这个名称显示在控制台上。
     * 比如:Task:app:transformClassesWithXXXForDe...
     */
    @Override
    String getName() {
        return "ZylTransform"
    }

    /**
     * 在项目中会有各种各样格式的文件,通过getInputType可以设置LifeCycleTransform接收的文件类型,
     * 此方法返回的类型是 Set<QualifiedContent.ContentType> 集合
     *
     */
    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }

    /**
     * 这个方法规定自定义 Transform 检索的范围
     */
    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.PROJECT_ONLY
    }

    /**
     * 表示当前 Transform 是否支持增量编译,我们不需要增量编译,所以直接返回 false 即可。
     *
     */
    @Override
    boolean isIncremental() {
        return false
    }

    /**
     *
     * @param transformInvocation
     * @throws TransformException
     * @throws InterruptedException
     * @throws IOException
     */
    @Override
    void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
        super.transform(transformInvocation)

        //拿到所有的class文件
        def inputs = transformInvocation.inputs
        inputs.each { transformInput->
            transformInput.directoryInputs.each { DirectoryInput directoryInput->
                File dir = directoryInput.file
                if (dir){
                   dir.traverse(type: FileType.FILES,nameFilter:~/.*\.class/) { file->
                        System.out.println("find class: "+file.name)
                   }
                }
            }

        }
    }
}
  1. 将自定义的 LifeCycleTransform 注册到 Gradle 插件中
public class LifeCyclePlugin implements Plugin<Project>{

    @Override
    void apply(Project project) {
        System.out.println("== LifeCyclePlugin Plugin gradle plugin ==")
        //注册transform
        def android = project.extensions.getByType(AppExtension)
        android.registerTransform(new LifeCycleTransform())
    }
}
  1. 再次在命令行中执行 ./gradlew clean assembledebug
    命令,可以看到LifeCycleTransform 检索出的所有 .class 文件
> Configure project :app
== LifeCyclePlugin Plugin gradle plugin ==

> Task :app:transformClassesWithZylTransformForDebug
find class: MainActivity.class
find class: BuildConfig.class

BUILD SUCCESSFUL in 7s

问题与总结

  1. 编译时提示我找不到LifeCycleTransform这个类,原因是LifeCycleTransform这个类当前命名的时候忘记加.groovy文件名后缀了,studio也不报错,显示一切正常
  2. 由于插件是本地包,你如果测试完gradle插件之后,删除本地插件文件夹,再生成一个带有自定义transform的插件。
  3. 报错Could not find com.android.tools.build:gradle:3.4.2.,解决办法添加mavenCentral()和google()仓库,注意添加的位置,如下:
apply plugin: 'com.android.application'
apply plugin: 'zyl.asm.lifecycle'

buildscript {
    repositories {
        //自定义插件的maven地址
        maven {url '../asm_lifecycle_repo'}
//        添加这两个仓库为了插件库里面的gradle:3.4.2版本依赖拉取,解决编译报错
        //Could not resolve all artifacts for configuration ':app:classpath'.    > Could not find com.android.
        //Could not find com.android.tools.build:gradle:3.4.2.
        mavenCentral()
        google()
    }

    dependencies {
        //加载自定义插件 group+module+version
        classpath 'com.okay.plugin:asm_lifecycle_pulgin:1.0.0'
    }
}
  1. 检索出的所有 .class 文件不一样多,是项目用到的gradle版本不一样导致的。
  • classpath 'com.android.tools.build:gradle:3.6.2'
> Configure project :app
== LifeCyclePlugin Plugin gradle plugin ==

> Task :app:transformClassesWithZylTransformForDebug
find class: MainActivity.class
find class: SizeConvertUtil.class
find class: BuildConfig.class
  • classpath 'com.android.tools.build:gradle:3.4.1'
== LifeCyclePlugin Plugin gradle plugin ==

> Task :app:transformClassesWithZylTransformForDebug
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R.class
find class: R.class
find class: R.class
find class: R.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R.class
find class: R$interpolator.class
find class: R$bool.class
find class: R$id.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R$styleable.class
find class: R$style.class
find class: R$anim.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$style.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class
find class: R.class
find class: R.class
find class: R$id.class
find class: R$styleable.class
find class: R$attr.class
find class: R.class
find class: R$interpolator.class
find class: MainActivity.class
find class: R$bool.class
find class: R$id.class
find class: R$mipmap.class
find class: SizeConvertUtil.class
find class: BuildConfig.class
find class: R$styleable.class
find class: R$style.class
find class: R$anim.class
find class: R$string.class
find class: R$color.class
find class: R$dimen.class
find class: R$integer.class
find class: R$layout.class
find class: R$attr.class
find class: R$drawable.class