12

Gradle之自定义插件

 3 years ago
source link: https://blog.csdn.net/mingyunxiaohai/article/details/103273480
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前面两篇了解了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
在这里插入图片描述

然后去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下面,内容如下图

在这里插入图片描述

最后去工程中使用插件

首先来到主工程的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来完成不同的逻辑即可。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK