Gradle自定义插件详解

首先认识plugin,plugin采用groovy语言来编写。

如果你对groovy语言不是很熟悉,请首先过一下groovy语法结构,groovy是运行于JVM的敏捷脚本语言,其最后会被编译成标准的JAVA语言。groovy语言最核心的应该是闭包,JAVA8引入的最新特性拉姆表达式,即是一个闭包,请参考相关文章,这里就不详细介绍了。

build.gradle引用插件语法为:

apply plugin: 'com.android.application'
apply plugin: "maven"

当然引用插件之前,需要加载驱动,即是 buildScrip中包含的代码,如下:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
    }
}

以上引用了 mave库 jcenter() 依赖了 gradle 2.3 ;因此如果引入自定义的plugin则首选需要加载自定义的驱动进来,后续会详解。 

1、自己项目中自定义插件。

如果仅仅是自己项目中来自定义插件,不对外发布,那么可以按照以下的语法来构建目录,代码结构图如下。

这里写图片描述

a、构建目录 buildSrc/src/main/groovy 本路径android studio会自动识别为 groovy项目。
b、在main目录中再构建 resources/META-INF/gradle-plugins,这个目录是groovy项目的资源文件目录。
例如,新建groovy文件 CustomPluginTest.groovy,代码如下:

    package bobo
    import org.gradle.api.Plugin;
    import org.gradle.api.Project;

    class CustomPluginTest implements Plugin<Project>{

        @Override
        void apply(Project project) {
            //增加闭包名称,闭包为customPlugin,是 CustomPluginTestExtension类型,因此CustomPluginTestExtension类型中的JaveBean类型的属性可以任意设置
            project.extensions.add("customPlugin",CustomPluginTestExtension)
            project.task("showPersonInfo") << {
                println("姓名:" + project.customPlugin.name)
                println("年龄:" + project.customPlugin.age)
                println("地址:" + project.customPlugin.address)
            }

            project.extensions.add("customFruitPlugin",CustomPluginTestExtensionFruit)
            project.task("showLoveFruit") << {
                println("喜欢的水果有:" + project.customFruitPlugin.apple + ", " + project.customFruitPlugin.orange + ", " + project.customFruitPlugin.banana)
            }
    }
    package bobo
    class CustomPluginTestExtension{
        def name = "init";
        def age = "init";
        def address = "init";
    }
buildSrc 中的  build.gradle的定义,引入groovy插件,并依赖 gradleApi()、localGroovy()。

apply plugin: 'groovy'

dependencies {
    compile gradleApi()
    compile localGroovy()
}

repositories {
    mavenCentral()
}

CustomPluginTest 是本插件的执行类,其继承了Plugin,并需要实现其方法apply。apply中的参数 Project是什么呢?我们都知道build.gradle有一个变量名 project(build.gradle中定义的所有对象均属于project,备注:groovy一切皆为对象)。其传过来的就是build.gradle的project,因此理解以上代码就非常容易了。定义一个扩展类增加到 project.extensions,本扩展类其实就是只用于set、get的JavaBean类。定义的别名 customPlugin 即是一个闭包,那么就可以在build.gradle中对其值进行设值了,请看以下build.gradle中对 customPlugin的赋值。

    apply plugin: 'MyInfo'
    customPlugin{
        name = "bobo"
        age = "25"
        address = "广东珠海"
    }

向 build.gradle中增加一个task,即是project.task(“xxx”),这里的代码增加一个 showPersonInfo 的task,当编译成功之后,可以看见android studio中的可视化模块Gradle projects 中的 app -> Tasks -> other中新增了一个
showPersonInfo的task, 右键运行,请查看以下输出结果:

这里写图片描述

这里写图片描述

**c、**groovy中可以新建自己的程序的包名和文件,当然文件是groovy文件,因此扩展名为 .groovy。
**d、**gradle-plugins中新建配置文件,扩展名为.properties,例如结构图中的MyInfo.properties。这里的文件名 即是将在 build.gradle 引入的插件名称。
其内部代码为 implementation-class=bobo.CustomPluginTest ;implementation-class=为固定的,bobo.CustomPluginTest为完整的类名(包括包名,请查看上面的代码结构图)
那怎么应用插件呢?MyInfo.properties 的文件名 MyInfo即是插件名,例如build.gradle中的引用:

apply plugin: 'MyInfo'
customPlugin{
    name = "bobo"
    age = "25"
    address = "广东珠海"
}

MyInfo.properties中的代码截图:

这里写图片描述

e、总结一下build.gradle识别自定义插件的过程? 按照 a、b 介绍的生产目录后,同步工程会自动生成一个groovy工程, build.gradle 引入插件 apply plugin: ‘MyInfo’ ,而根据这个引入的插件会找到定义的 MyInfo.properties文件,那么MyInfo.properties配置文件中引入的类其实是 CustomPluginTest,根据CustomPluginTest则将build.gradle的project传过去,则其内部定义的代码即是 在build.gradle中定义的代码。

f、根据 e 中的build.gradle对插件的识别,其实也可以不用另外新建 groovy项目,完全可以将 buildSrc中定义的 CustomPluginTest 和 CustomPluginTestExtension挪到 build.gradle文件中,只是这样build.gradle的 代码非常长,也非常复杂。例如以下截图,我们在build.gradle中定义了插件 GreetingPlugin,其实现和 CustomPluginTest完全一致。

这里写图片描述

2、以上用两种方式实现了自定义插件,这两种方式只能在本项目中引用,如果我们要发布到mavan库,然后供其项目或者其他人使用怎么办呢?后续将对这进行讲解。

**a、**android studio中新建一个 Android Librarys项目,然后除了主目录删除主目录中的所有文件。
b、还记得上面怎么定义的buildSrc的吗?在新建的 Android Librarys项目中按照新建 buildSrc的步骤构建groovy项目。
请看以下截图:
这里写图片描述

c、以上定义的插件 CustomPluginOne 和buildSrc插件的定义方式完全一样,这样就不细说了。

d、这里和 buildSrc 不同的地方就是,buildSrc可以自动的去识别插件,而这里的 pluginlibrary 是无法自动识别的,则首先需要发布到maven库,然后在app的build.gradle中 引入驱动 再引入插件,请看如下代码:

   pluginlibrary 中的 build.gradle定义 :

    apply plugin: 'groovy'
    apply plugin: 'maven'
    dependencies{
        compile gradleApi()
        compile localGroovy()
    }

    repositories {
        mavenCentral()
    }

    group='com.bobo.plugin'
    version='3.0.0'
    uploadArchives{
        repositories {
            mavenDeployer {
                repository(url: uri('../publish'))
            }
        }
    }

首先,引用maven 和 groovy库,然后repositories引入 mavenCentral(),再定义 group 和 version,uploadArchives内部的为maven发布地址,我们这里发布的地址为本地, 即使根目录的 publish中。

其次,当我们定义了以上 pluginlibrary 中的 build.gradle之后,android中同步工程,当同步成功之后,模块 pluginlibrary中会显示 一个上传任务,请查看截图:
这里写图片描述

右键执行uploadArchives,则刷新工程,可以看见maven已经发布到了本地,请看下图:

这里写图片描述

第三,既然发布成功了,那么以下将在app的build.gradle中引用插件,入以下截图:

这里写图片描述

首选加载驱动,即是加载maven库 publish,然后依赖 引入 com.bobo.plugin:pluginlibrary:3.0.0,结构为 groupId + 项目名称 + 版本号。最后就可以加载插件了 apply plugin: ‘testPluginPro’。同步成功之后,则在执行自定义插件中定义的任务 CustomPluginOne,执行结果如下:

这里写图片描述

以下贴上 pluginlibrary 中代码:

CustomPluginOne.groovy

package com.bobo.plugin

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

class CustomPluginOne implements Plugin<Project>{
    @Override
    void apply(Project project) {
        project.extensions.add("personInfo", CustomPluginOneExtension)

        project.task("personInfoTask")<< {
            println("姓名: " + project.personInfo.name)
            println("年龄: " + project.personInfo.age)
            println("性别: " + project.personInfo.sex)
            println("家庭住址: " + project.personInfo.address)
            println("公司: " + project.personInfo.company)
            println("公司住址: " + project.personInfo.companyAddress)
        }
    }
}
CustomPluginOneExtension.groovy

package com.bobo.plugin

class CustomPluginOneExtension{
    def name = "";
    def age = 0
    def sex = "男"
    def address = ""
    def company = ""
    def companyAddress = ""
}
资源文件 testPluginPro.properties

implementation-class=com.bobo.plugin.CustomPluginOne
pluginlibrary 的 build.gradle

apply plugin: 'groovy'
apply plugin: 'maven'
dependencies{
    compile gradleApi()
    compile localGroovy()
}

repositories {
    mavenCentral()
}

group='com.bobo.plugin'
version='3.0.0'
uploadArchives{
    repositories {
        mavenDeployer {
            repository(url: uri('../publish'))
        }
    }
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页