转载

Gradle之自定义插件

Gradle之自定义插件

前面两篇了解了Gradle的基础知识,最终目的就是为了自己能写出Gradle插件来解决现实项目中的问题。现在Gradle自定义插件用的越来越广泛,插件化,热修复,性能优化,指标检测,多渠道打包等等都会用到Gradle插件。

自定义Gradle插件的方式有三种,代码都差不多,都是必须实现 Plugin<T> 这个接口,然后实现接口中的 apply 方法。只不过写的地方不一样。

第一种在build.gradle

在AndroidStido中创建一个新项目,然后直接在app目录下的build.gradle文件中写插件

class MyPlugin implements Plugin<Project>{
    @Override
    void apply(Project target) {
        println('MyPlugin执行了')
        target.task("mytask"){
            doLast {
                println('MyPlugin中的task执行了')
            }
        }
    }
}

定义一个MyPlugin插件实现Plugin接口。然后在apply方法中自定义一个task。一个简单的插件就完成了。

然后在当前build.gradle文件中引入插件

apply plugin: MyPlugin

OK完成,然后在控制台执行一下我们自己的task,window下命令: gradlew mytask 输出如下,Mac在gradlew前面加个./

> Configure project :app
MyPlugin执行了

> Task :app:mytask
MyPlugin中的task执行了

使用这种方式可以很快的创建一个插件,不过缺点也很明显:

  1. 该plugin只能被当前build.gradle引用。
  2. 一个插件不可能就上面那几行代码,插件代码全写到这一个文件中,会让这个文件非常臃肿不好维护。

第二种在buildSrc文件夹下

buildSrc是Gradle中的默认插件目录,编译的时候Gradle会自动识别这个目录,将其内的代码编译成插件。

可以先创建一个java的module,然后修改一个build.gradle文件为下面

apply plugin: 'groovy'

只写上面的一句话就行。因为需要写一个groovy项目,所以把main文件夹下的原来的java入口文件夹直接改成groovy,这种方式比较方便。

或者重新建一个groovy文件夹,然后把这个文件夹设置为项目的入口文件设置方式如下

sourceSets {
    main {
        groovy {
            srcDir 'src/main/groovy'
        }
    }
}

然后开始在groovy文件夹下写插件代码 com.hsm.buildsrc.MyPlugin

class MyPlugin implements Plugin<Project> {
    @Override
    void apply(Project target) {
        println('buildSrc中MyPlugin执行了')
        target.task("mytask"){
            doLast {
                println('buildSrc中MyPlugin中的task执行了')
            }
        }
    }
}

写完插件,怎么让gradle知道哪个是插件呢?

  • 在main目录下新建resources目录,然后在resources目录里面再新建META-INF目录,再在META-INF里面新建gradle-plugins目录。最后在gradle-plugins目录里面新建properties文件
  • properties文件的名字可以随便取,后面用到的时候就用这个取好的名字,这里就直接使用插件的包名了 com.hsm.buildsrc 。在properties文件中指明我们自定义的插件的类 implementation-class=com.hsm.buildsrc.MyPlugin

Gradle之自定义插件

然后去app中的build.gradle文件中引入插件

apply plugin: 'com.hsm.buildsrc'

最后控制台输入命令验证插件 gradlew mytask

> Configure project :app
buildSrc中MyPlugin执行了

> Task :app:mytask
buildSrc中MyPlugin中的task执行了

使用这种方式写的插件,整个工程中的所有module都可以引用到,而且插件代码在自己的文件夹中,也方便维护。

第三种自定义module,上传maven

第二种方式写的插件只能在当前工程中使用,有时候我们需要插件能多个工程都能使用,比如我们的项目中可以使用butterknife的插件,可以使用greenDao的插件。这就需要把我们的插件上传到别的仓库中比如maven。

在项目中新建一个module,这里命名为plugin_module,可以是java module也可以是android Library反正最后都得改嘿嘿。最好建个java的改的少。

修改build.gradle文件为下面

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

dependencies {
    //gradle sdk
    implementation gradleApi()
    //groovy sdk
    implementation localGroovy()
}
//uploadArchives是将已经自定义好了插件打包到本地Maven库里面去,
//也可以选择打包到远程服务器中。其中, group和version是我们之后配置插件地址时要用到的。
group='com.hsm.plugin_module'
version='1.0'
uploadArchives {
    repositories {
        mavenDeployer {
            //本地的Maven地址:当前工程下
            repository(url: uri('./my-plugin'))
            //提交到远程服务器:
            // repository(url: "http://www.xxx.com/repos") {
            //    authentication(userName: "admin", password: "admin")
            // }
        }
    }
}
  • dependencies中添加gradle sdk和groovy sdk之后,我们建的这个module就可以开发gradle的工程了。
  • uploadArchives是将已经自定义好了插件打包到本地Maven库里面去,也可以选择打包到远程服务器中
  • group和version是别的项目引用的时候使用的组名和版本号

开始编写插件:

class MyPlugin implements Plugin<Project> {
    @Override
    void apply(Project target) {
        println('plugin_module 中MyPlugin执行了')
        target.task("mytask"){
            doLast {
                println('plugin_module中MyPlugin中的task执行了')
            }
        }
    }
}

然后 跟第二步中的步骤一样 创建resources目录和resources下面的各个目录和文件。这里使用的包名是com.hsm.plugin_module

执行gradle命令上传插件jar包到maven仓库 gradlew uploadArchives ,执行完之后jar包就上传到了我们前面定义的./my-plugin下面,内容如下图

Gradle之自定义插件

最后去工程中使用插件

首先来到主工程的build.gradle文件夹下引入插件的仓库和依赖

buildscript {
    repositories {
        maven {
            //本地仓库地址
            url uri('D:/androiddemo/5/GradlePlugin/plugin_module/my-plugin')
        }
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        ////格式为-->group:module:version
        classpath 'com.hsm.plugin_module:plugin_module:1.0'
    }
}
  • 设置本地仓库的地址
  • 在dependencies中引入插件,格式为group:module:version

然后去app文件夹下的build.gradle文件中引入插件

apply plugin: 'com.hsm.plugin_module'

到这里就OK了,控制台中输入命令验证: gradlew mytask

> Configure project :app
plugin_module 中MyPlugin执行了

> Task :app:mytask
plugin_module中MyPlugin中的task执行了

插件的扩展 Extension

我们在集成tinker的时候,会在build.gradle文件中配置tinkerPatch的各种参数比如oldApk ,useSign,buildConfig 等等, 这就是在配置插件中的参数或者属性,而插件的扩展Extension就是用来把这些参数传回插件中。

现在给第三步中的插件添加一个扩展Extension

在插件的module中新建一个实体类MyExtension

package com.hsm.plugin_module

class MyExtension {
    int id
    String name
}

然后去MyPlugin插件类中添加扩展

class MyPlugin implements Plugin<Project> {
    @Override
    void apply(Project target) {
        println('plugin_module 中MyPlugin执行了')
        //1.添加插件扩展到project.extensions集合中
        target.extensions.add('myextension',MyExtension)
        target.task("mytask"){
            doLast {
                println('plugin_module中MyPlugin中的task执行了')
                //2.获取外界配置的 TestExtension
                MyExtension extension = target.myextension
                //3.输出插件扩展属性
                println ">>>>>> name: ${extension.name} id:${extension.id}"
            }
        }
    }
}
  • 通过project.extensions.add方法将自定义的实体添加到扩展中,并起个名字
  • 可以通过起的名字拿到扩展的实体类
  • 最后拿到类中的属性

修改完之后重新上传到maven,如果版本号没变,最好先把仓库以前的文件删掉在上传

上传完成之后去项目app目录下的build.gradle中使用

apply plugin: 'com.hsm.plugin_module'

myextension{
    id 123
    name 'chs'
}

控制台中执行命令验证: gradlew mytask

> Configure project :app
plugin_module 中MyPlugin执行了

> Task :app:mytask
plugin_module中MyPlugin中的task执行了
>>>>>> name: chs id:123

OK,Gradle创建插件的流程完毕,想要完成更加复杂的功能,只需要在该插件中定义各种各样的task来完成不同的逻辑即可。

原文  https://chsmy.github.io/2019/11/28/architecture/Gradle之自定义插件/
正文到此结束
Loading...