Gradle之自定义插件
前面两篇了解了Gradle的基础知识,最终目的就是为了自己能写出Gradle插件来解决现实项目中的问题。现在Gradle自定义插件用的越来越广泛,插件化,热修复,性能优化,指标检测,多渠道打包等等都会用到Gradle插件。
自定义Gradle插件的方式有三种,代码都差不多,都是必须实现Plugin<T>
这个接口,然后实现接口中的apply
方法。只不过写的地方不一样。
第一种在build.gradle
在AndroidStido中创建一个新项目,然后直接在app目录下的build.gradle文件中写插件1
2
3
4
5
6
7
8
9
10
11class MyPlugin implements Plugin<Project>{
@Override
void apply(Project target) {
println('MyPlugin执行了')
target.task("mytask"){
doLast {
println('MyPlugin中的task执行了')
}
}
}
}
定义一个MyPlugin插件实现Plugin接口。然后在apply方法中自定义一个task。一个简单的插件就完成了。
然后在当前build.gradle文件中引入插件1
apply plugin: MyPlugin
OK完成,然后在控制台执行一下我们自己的task,window下命令:gradlew mytask
输出如下,Mac在gradlew前面加个./1
2
3
4
5> Configure project :app
MyPlugin执行了
> Task :app:mytask
MyPlugin中的task执行了
使用这种方式可以很快的创建一个插件,不过缺点也很明显:
- 该plugin只能被当前build.gradle引用。
- 一个插件不可能就上面那几行代码,插件代码全写到这一个文件中,会让这个文件非常臃肿不好维护。
第二种在buildSrc文件夹下
buildSrc是Gradle中的默认插件目录,编译的时候Gradle会自动识别这个目录,将其内的代码编译成插件。
可以先创建一个java的module,然后修改一个build.gradle文件为下面1
apply plugin: 'groovy'
只写上面的一句话就行。因为需要写一个groovy项目,所以把main文件夹下的原来的java入口文件夹直接改成groovy,这种方式比较方便。
或者重新建一个groovy文件夹,然后把这个文件夹设置为项目的入口文件设置方式如下1
2
3
4
5
6
7sourceSets {
main {
groovy {
srcDir 'src/main/groovy'
}
}
}
然后开始在groovy文件夹下写插件代码 com.hsm.buildsrc.MyPlugin1
2
3
4
5
6
7
8
9
10
11class 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文件中引入插件1
apply plugin: 'com.hsm.buildsrc'
最后控制台输入命令验证插件gradlew mytask
1
2
3
4
5> 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文件为下面1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25apply 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是别的项目引用的时候使用的组名和版本号
开始编写插件:1
2
3
4
5
6
7
8
9
10
11class 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文件夹下引入插件的仓库和依赖1
2
3
4
5
6
7
8
9
10
11
12
13
14
15buildscript {
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文件中引入插件1
apply plugin: 'com.hsm.plugin_module'
到这里就OK了,控制台中输入命令验证:gradlew mytask
1
2
3
4
5> Configure project :app
plugin_module 中MyPlugin执行了
> Task :app:mytask
plugin_module中MyPlugin中的task执行了
插件的扩展 Extension
我们在集成tinker的时候,会在build.gradle文件中配置tinkerPatch的各种参数比如oldApk ,useSign,buildConfig 等等, 这就是在配置插件中的参数或者属性,而插件的扩展Extension就是用来把这些参数传回插件中。
现在给第三步中的插件添加一个扩展Extension
在插件的module中新建一个实体类MyExtension1
2
3
4
5
6package com.hsm.plugin_module
class MyExtension {
int id
String name
}
然后去MyPlugin插件类中添加扩展1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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中使用
1 | apply plugin: 'com.hsm.plugin_module' |
控制台中执行命令验证:gradlew mytask
1
2
3
4
5
6> Configure project :app
plugin_module 中MyPlugin执行了
> Task :app:mytask
plugin_module中MyPlugin中的task执行了
>>>>>> name: chs id:123
OK,Gradle创建插件的流程完毕,想要完成更加复杂的功能,只需要在该插件中定义各种各样的task来完成不同的逻辑即可。