Gradle中插件可以分为两类:脚本插件和对象插件。
脚本插件
脚本插件就是一个普通的gradle构建脚本,通过在一个foo.gradle脚本中定义一系列的task,另一个构建脚本bar.gradle通过
apply from:'foo.gradle'
即可引用这个脚本插件。
首先在项目根目录下新建一个config.gradle文件,在该文件中定义所需的task。
//config.gradle
project.task("showConfig") {
doLast {
println("$project.name:showConfig")
}
}
然后在需要引用的module的构建脚本中引用config.gradle
,例如在app.gradle
中,由于config.gradle
建立在根目录下,与app这个模块平级,所以需要注意路径问题../config.gradle
//app.gradle
apply from: '../config.gradle'
就是这么简单,此时运行gradle构建即可执行showConfig这个task,
garretdeMacBook-Pro:CustomPlugin garretwei$ ./gradlew showConfig
> Task :app:showConfig
app:showConfig
对象插件
对象插件是指实现了org.gradle.api.Plugin接口的类。Plugin接口需要实现
void apply(T target)
这个方法。该方法中的泛型指的是此Plugin可以应用到的对象,而我们通常是将其应用到Project对象上。
编写对象插件主要有三种方式:
-
直接在gradle脚本文件中
-
在buildSrc目录下
-
在独立的项目下
在gradle脚本文件中
直接在gradle脚本中编写这个方式是最为简单的。打开app.gradle
文件,在其中编写一个类实现Plugin接口。
//app.gradle
class CustomPluginInBuildGradle implements Plugin<Project> {
@Override
void apply(Project target) {
target.task('showCustomPluginInBuildGradle'){
doLast {
println("task in CustomPluginInBuildGradle")
}
}
}
}
然后通过插件类名引用它
//app.gradle
apply plugin: CustomPluginInBuildGradle
执行插件中定义的task
garretdeMacBook-Pro:CustomPlugin garretwei$ ./gradlew -q showCustomPluginInBuildGradle
task in CustomPluginInBuildGradle
在buildSrc目录下
除了直接写在某个模块的构建脚本中,我们还可以将插件写在工程根目录下的buildSrc目录下,这样可以在多个模块之间复用该插件。
虽然buildSrc是Gradle在项目中配置自定义插件的默认目录,但它并不是标准的Android工程目录,所以使用这种方式需要我们事先手动创建一个buildSrc目录。目录结构如下:
buildSrc目录结构
在buildSrc/src/main/groovy目录下创建自定义plugin,并在build.gradle中引用groovy插件
// buildSrc/build.gradle
apply plugin: 'groovy'
dependencies {
compile gradleApi()
compile localGroovy()
}
然后编写plugin代码
class CustomPluginInBuildSrc implements Plugin<Project> {
@Override
void apply(Project project) {
project.task('showCustomPluginInBuildSrc') {
doLast {
println('task in CustomPluginInBuildSrc')
}
}
}
}
由于buildSrc目录是gradle默认的目录之一,该目录下的代码会在构建是自动编译打包,并被添加到buildScript中的classpath下,所以不需要任何额外的配置,就可以直接被其他模块的构建脚本所引用。
注意这里引用的方式可以是通过类名引用,也可以通过给插件映射一个id,然后通过id引用。
通过类名引用插件的需要使用全限定名,也就是需要带上包名,或者可以先导入这个插件类,如下
apply plugin: com.gary.plugin.CustomPluginInBuildSrc
或者
import com.gary.plugin.CustomPluginInBuildSrc
apply plugin: CustomPluginInBuildSrc
通过简单的id的方式,我们可以隐藏类名等细节,使的引用更加容易。映射方式很简单,在buildSrc目录下创建resources/META-INF/gradle-plugins/xxx.properties,这里的xxx也就是所映射的id,这里我们假设取名myplugin。具体结构可参考上文buildSrc目录结构。
myplugin.properties文件中配置该id所对应的plugin实现类
implementation-class=com.gary.plugin.CustomPluginInBuildSrc
此时就可以通过id来引用对于的插件了
//app.gradle
apply plugin: 'myplugin'
在独立工程下
在buildSrc下创建的plugin只能在该工程下的多个模块之间复用代码。如果想要在多个项目之间复用这个插件,我们就需要在一个单独的工程中编写插件,将编译后的jar包上传maven仓库。
这里为了不增加复杂度,我们还是在该工程下创建一个standaloneplugin模块。只需要明白我们完全可以在一个独立的工程下来编写插件。
standAlonePlugin目录结构
从目录结构来看,和buildSrc目录是一致的。区别在于buildSrc下的代码在构建时会自动编译并被引用。而我们在独立项目中编写的插件如果要能正确的被引用到,需要上传到maven仓库中,然后显式地在需要引用的项目中的buildSrcipt中添加对该构件的依赖。
插件代码
class StandAlonePlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.task('showStandAlonePlugin') {
doLast {
println('task in StandAlonePlugin')
}
}
}
}
插件项目构建脚本
apply plugin: 'groovy'
apply plugin: 'maven'
dependencies {
compile gradleApi()
compile localGroovy()
}
group = 'com.gary.plugin'
version = '1.0.0'
uploadArchives {
repositories {
mavenDeployer {
repository(url: uri('../repo'))
}
}
}
这里与buildSrc不同的是,我们引用了apply plugin 'maven'
,通过maven插件,我们可以轻松的配置group,version 以及 uploadArchives的相关属性,然后执行./gradlew uploadArchives
这个任务,就可以将构件打包后上传到maven仓库了。同样为了示例简单,我们上传到一个本地仓库repository(url: uri('../repo'))
中。
上传之后就可以在项目根目录下找到repo
这个目录了。最后我们通过给根目录下的build.gradle配置buildScript的classpath,就可以引用这个插件了。注意,classpath的格式为group:artifact:version
buildscript {
repositories {
maven {
url uri('repo')
}
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.gary.plugin:standaloneplugin:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
引用插件
//app.gradle
apply plugin: 'standAlonePlugin'
执行StandAlonePlugin中定义的任务
./gradlew -q showStandAlonePlugin
task in StandAlonePlugin
总结
-
插件分为脚本插件和对象插件。
-
脚本插件通过
apply from: 'foo.gradle'
引用。 -
对象插件可以在当前构建脚本下直接编写,也可以在buildSrc目录下编写,还可以在完全独立的项目中编写,通过插件类名或是id引用。
apply plugin: ClassName
或者apply plugin:'pluginid'
本文所编写的插件代码只是起到简单说明,主要介绍插件编写方式。实际插件编写过程中需要用到的Extension,以及Project和Gradle相关的生命周期方法等api并未涉及。相关知识点可以参考本系列文章中的【实战,从0到1完成一款Gradle插件】。
最后
更多Android进阶技术,面试资料系统整理分享,职业生涯规划,产品,思维,行业观察,谈天说地。可以加Android架构师群;701740775。