Gradle自定义插件的三种方式

gradle是一种构建工具,用来控制代码的编译、构建、打包等过程,自定义Gradle在Android中应用是很广泛的,比如在gradle构建过程中使用字节码技术、默认的Android项目中应用了很多插件,比如java、groovy、com.android.application等,了解Gradle插件有助于更好的理解生成APK的过程。

自定义插件三种方式:

  • build script:在build.gradle脚本中直接编写,只能在本文件内使用;
  • buildSrc项目:新建一个名为buildSrc的Module,只能在本项目中使用;
  • 独立的项目:在独立的项目中编写插件,发布到本地或者远程maven仓库供其他项目使用。

1. 基础知识

本文基于Android进行讲解,实际上任何一个gradle project都可以,阅读本文你可以需要具备基本的gradle知识、groovy语法,可以参考我的两外两篇文章。


建议有gradle基础的和英文水平较高的直接阅读Gradle官方文档:Gradle custom_plugins

2. 方式一:build script

直接在脚本文件中编写插件,线上项目一般不这样做。

2.1 创建Project编辑project下的buid.gradle文件

创建一个project,直接在app module下的build.gradle脚本文件编写插件。
示例:
Build script1
编辑build.gradle文件,新增插件GreetingPlugin,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
println "GreetingPlugin"
project.task('hello') {
doLast {
println 'Hello from the GreetingPlugin'
}
}
}
}

//应用插件
apply plugin: GreetingPlugin

不推荐这样做:

  • 维护成本高:造成build.gradle文件过于臃肿
  • 无法复用:plugin只能在app module中使用,不能给其他module和project使用。

2.2 build.gradle优化的方式

通过apply from: '../script/xxx.gradle'应用xxx.gradle脚本中编写的插件。
创建script/test.gralde文件并添加以上脚本内容。如图:
Build script2
app module使用,添加apply from: '../script/test.gradle'即可应用test.gralde脚本。
Build script3

3.方式二:buildSrc

一般用于本地调试使用

3.1 搭建buildSrc module

在工程中新建buildSrc目录,名称一定不能写错,在buildSrc目录下建立如下目录和文件:

1
2
3
4
src/
main/
groovy/
build.gradle

编辑build.gradle文件,添加如下内容:

1
2
3
4
5
6
7
8
plugins {
id 'groovy'
}

dependencies {
implementation gradleApi()
implementation localGroovy()
}

项目结构如下:
buildSrc1
点击sync或者buid project(这一步必须),会生成build目录,groovy目录也会变成源文件目录,之后就可以创建包和源代码。

3.2 写插件

在groovy目录下新建包(new->package):com.learn.plugin。
新建MyPlugin.groovy文件,必须以.groovy为后缀。添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
package com.learn.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project

class MyPlugin implements Plugin<Project> {

@Override
void apply(Project project) {
println("Hello gradle plugin")
}
}

到这里插件已经写好了,在其他地方使用即可。

3.3 其他module中使用buildSrc中的插件

在app module下的build.gradle中应用插件:

1
apply plugin: com.learn.plugin.MyPlugin

在终端输入如下命令验证:

1
./gradlew assemble

或者直接Run也可以。
输出如下内容表示成功:

1
2
> Configure project :app
Hello gradle plugin

3.4 总结

  • module名称必须是buildSrc
  • 一般本地调试使用,项目中使用都是远程jar包形式,即第三种方式

4.方式三:独立项目

这种方式是项目中常用的,最后生成的是jar包,可以发布在本地或者远程仓库(jcenter、maven),方便其他项目使用。

4.1 新建写插件的module

新建一个module(新建一个工程也可以,因为最后生成和使用都是jar包的形式),module名称随意,只保留build.gradle文件和src/main目录,其余文件全部删掉。
修改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
25
26
27
28
apply plugin: 'groovy' //必须,groovy写插件必须
apply plugin: 'maven' //要想发布到Maven,此插件必须使用

dependencies {
implementation gradleApi() //必须
implementation localGroovy() //必须
}
repositories {
mavenCentral() //必须
}

def group='com.hh.cus_plugin' //组
def artifactId='myGradlePlugin' //唯一标示
def version='1.0.0' //版本

def uploadRepo = new File(System.getProperty("user.home") + "/.hhrepo")
//将插件打包上传到本地maven仓库
uploadArchives {
repositories {
mavenDeployer {
pom.groupId = group
pom.artifactId = artifactId
pom.version = version
//指定本地maven的路径,在项目根目录下
repository(url: uri(uploadRepo))
}
}
}

相比buildSrc方案,增加了Maven的支持和uploadArchives这样一个Task,这个Task的作用是为了将插件打包上传到本地maven仓库。
这里使用的本地地址:/Users/username(你电脑的名称)/.hhrepo

4.2 写插件

同方式二,这里直接给出结果:
AGP3

4.3 发布

在终端中执行./gradlew uploadArchives指令,或者展开Android Studio右侧的Gradle,找到对应module->uploadArchivesTask,就可以将插件部署到相应的目录下。
AGP3-2,-w337
验证结果:
-w495

4.4 其他项目使用

修改project(根目录)下的build.gradle文件内容,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
buildscript {
ext.kotlin_version = "1.4.32"
repositories {
google()
jcenter()
maven {
url uri(System.getProperty("user.home") + "/.hhrepo") //指定本地maven的路径
}
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.hh.cus_plugin:myGradlePlugin:1.0.0"
}
}
...

在app中使用,修改app下的build.gradle,添加如下内容:

1
apply plugin: com.ccc.plugin.PluginTest//插件类的全限定名

在终端输入如下命令验证:

1
./gradlew assemble

或者直接Run也可以,看到相关提示则成功。

4.5 总结

  • 项目中一般使用这种方式,方便项目插件化

5. 拓展

有人可能见过通过META-INF中properties配置插件,没错,这种配置是比较推荐的,对于提供独立自定义插件的JAR,强烈推荐这种做。
一般插件很少直接使用插件类的全限定名调用,比如:

1
2
//不推荐
apply plugin:com.ccc.plugin.PluginTest

基本上都是通过插件名或者叫插件id调用,比如官方的java、groovy、com.android.application等,都是通过如下配置使用:

1
2
3
4
5
6
7
8
9
//推荐
apply plugin:'插件名'
apply plugin:'groovy'
apply plugin:'com.android.application'
或者
plugins{
id '插件名'
id 'java'
}

这样做的原因:可能是不想插件类暴露出来吧,可以自定义别名。(以后知道原因了再更新)

配置别名步骤:
在main目录下新建resources/META-INF/gradle-plugins目录,名称不能随意填写。
gradle-plugins下新建name(插件名).properties文件,这个name就是后面要使用的,如图:

其他module使用这个插件:

1
2
3
4
5
apply plugin:'hhhhh'
或者
plugins{
id 'hhhhh'
}

执行./gradlew assemble验证

6. 总结

开发gradle插件掌握方式三就行了,关键是项目里面有相关的内容能看懂就行了,比如字节码插桩、编译优化等都会涉及AGP的内容。再此安利:Gradle userguide

-------------本文结束感谢您的阅读-------------
如果本篇文章对你有帮助,请作者喝杯咖啡吧~