一、以库项目形式创建插件
1.创建项目
如果仅仅是自己项目中来自定义插件,不对外发布,那么可以按照以下的语法来构建目录
1.1 创建一个Module,选择Java Library项目,项目名称必须是 buildSrc,否则插件不被识别
1.2 构建目录 buildSrc/src/main/groovy 本路径android studio会自动识别为 groovy类。
1.3、在main目录中再构建 resources/META-INF/gradle-plugins,这个目录是groovy项目的资源文件目录。
注意,插件的代码可以是java实现,编程方式比较繁琐,这里我们使用groovy语言。
1.4 配置项目插件依赖
buildSrc 中的 build.gradle的定义,引入groovy插件,并依赖 gradleApi()、localGroovy()。
apply plugin:'groovy' #必须
group='com.ncf.plg'
version='3.0.0'
dependencies {
implementation gradleApi() #必须
implementation localGroovy() #必须
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
repositories {
mavenCentral() #必须
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
2、代码实现
新建groovy文件 CustomPluginTest.groovy,代码如下
package com.ncf.plg
import org.gradle.api.Plugin
import org.gradle.api.Project
class CustomPluginTest implements Plugin<Project>{
@Override
void apply(Project project) {
//增加闭包名称,闭包为customPlugin,是 CustomPluginTestExtension类型,因此CustomPluginTestExtension类型中的JaveBean类型的属性可以任意设置
project.extensions.add("personInfo",PersonInfo) //personInfo用于build.gradle中添加配置块
project.task("showPersonInfo") << {
if(project.personInfo==null) return ;
println("姓名:" + project.personInfo.name)
println("年龄:" + project.personInfo.age)
println("地址:" + project.personInfo.address)
}
project.extensions.add("bookInfo",BookInfo);
project.task("showBookInfo",dependsOn:"showPersonInfo" ) << {
//注意,showBookInfo依赖showPersonInfo,dependsOn:"showPersonInfo"
def book = project.extensions.findByType(BookInfo);
println("喜欢的书籍:" + book.name + ", " + book.id + ", " + book.price+'元'+','+book.address+","+book.isbn);
}
}
}
PersonInfo类
package com.ncf.plg
class PersonInfo {
def name = "init";
def age = "init";
def address = "init";
}
BookInfo类
package com.ncf.plg
class BookInfo {
def name = "《红楼们》";
def isbn = "SW.SH.CN.I.20181227";
def address = "北京市海淀区西北旺";
def price = 25.9f
def id = 'BS1001029'
}
配置MyCustomPlugin.properties
implementation-class=com.ncf.plg.CustomPluginTest
3、使用插件
在app项目的build.gradle中,我们引用插件
import com.ncf.plg.PersonInfo
apply plugin: 'MyCustomPlugin' //properties的名称
personInfo{
name='张三'
age=25
address='北京市海淀区朝阳路'
}
4、调用任务
执行如下命令
gradle showBookInfo 【如果是windows系统,调用gradlew showBookInfo】
执行结果如下
> Configure project :app
> Task :app:showPersonInfo
姓名:张三
年龄:25
地址:北京市海淀区朝阳路
> Task :app:showBookInfo
喜欢的书籍:《红楼们》, BS1001029, 25.9元,北京市海淀区西北旺,SW.SH.CN.I.20181227
二、发布到本地Maven仓库
对于一些插件,希望通过共享的方式让所有人都能使用,我们需要做的是上传插件,由于buildSrc目录下的插件是自动加载,为了展示效果,我们将buildSrc更名成其他项目名,比如MyGradlePlugin
同时,修改setting.gradle中的:buildSrc为:MyGradlePlugin
://blog.youkuaiyun.com/eclipsexys/article/details/50973205
1.在build.gradle中添加uploadArchives 块
apply plugin:'groovy' #必须
apply plugin: 'maven' #要想发布到Maven,此插件必须使用
def group='com.ncf.plg'
def version='3.0.0'
def artfactid='myGradlePlugin'
dependencies {
implementation gradleApi() #必须
implementation localGroovy() #必须
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
repositories {
mavenCentral() #必须
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
uploadArchives {
repositories {
mavenDeployer {
repository(url: uri('../public')) //注意相对路径,在主项目目录下
}
pom.groupId=group
pom.artifactId=artfactid
pom.version=version
}
}
这里增加了Maven的支持和uploadArchives这样一个Task,这个Task的作用就是将该Module部署到本地的repo目录下。
在终端中执行gradle uploadArchives指令,将插件部署到repo目录下
当插件部署到本地后,就可以在主项目中引用插件了。当插件正式发布后,可以把插件像其它module一样发布到中央库,这样就可以像使用中央库的库项目一样来使用插件了。
2、修改MyCustomPlugin.properties为插件包名,我这里是com.ncf.plugin.properties,这个很重要,在项目中引用是通过该文件名的
apply plugin: 'com.ncf.plugin'
3、引用插件
在buildSrc中,系统自动帮开发者自定义的插件提供了引用支持,但自定义Module的插件中,开发者就需要自己来添加自定义插件的引用支持。在主项目的build.gradle文件中,添加如下所示的脚本:
buildscript {
repositories {
//省略其他仓库
maven {
url uri('./public') //注意相对路径,和app目录并列
}
}
dependencies {
//省略其他环境遍历
classpath 'com.ncf.plg:MyGradlePlugin:3.0.0'
}
}
其中,classpath指定的路径,就是类似compile引用的方式:
classpath '[groupId]:[artifactId]:[version]'
配置完毕后,就可以在app项目中使用自定义的插件了
在app的build.gradle引入
apply plugin: 'com.ncf.plugin'
personInfo{
name='张三'
age=25
address='北京市海淀区朝阳路'
}
4、插件改进
引入插件之后,执行如下命令可以一遍更新插件,一边实时预览效果
gradle uploadArchives && gradle showPersonInfo
执行后我们发现,发布后的插件不同于buildSrc项目,我们在下面的方法中获取不到我们配置的personInfo信息
project.task("showPersonInfo") << {
if(project.personInfo==null) return ;
println("姓名:" + project.personInfo.name)
println("年龄:" + project.personInfo.age)
println("地址:" + project.personInfo.address)
}
问题处在哪里呢?
我们要知道,gradle插件执行分为2个周期,第一个是config周期,另一个是task执行周期,在config周期中插件只能获取到默认配置信息,而上述代码块本身处于config周期,因此,获取不到gradle中配置的信息,如何解决这个问题呢?
这里我们使用doFirst/doLast即可
package com.ncf.plg
import org.gradle.api.Plugin
import org.gradle.api.Project
class CustomPluginTest implements Plugin<Project>{
@Override
void apply(Project project) {
//增加闭包名称,闭包为customPlugin,是 CustomPluginTestExtension类型,因此C
ustomPluginTestExtension类型中的JaveBean类型的属性可以任意设置
project.extensions.add("personInfo",PersonInfo) //personInfo用于build.gradle中添加配置块
def showPersonTask = project.task("showPersonInfo") {
println '配置 showPersonInfo'
}
showPersonTask.doLast{
println("姓名:" + project.personInfo.name)
println("年龄:" + project.personInfo.age)
println("地址:" + project.personInfo.address)
}
project.extensions.add("bookInfo",BookInfo);
def showBookTask = project.task("showBookInfo",dependsOn:"showPersonInfo" ) {
println '配置 showBookInfo'
}
showBookTask.doFirst{
//注意,showBookInfo依赖showPersonInfo,dependsOn:"showPersonInfo"
def book = project.extensions.findByType(BookInfo);
println("喜欢的书籍:" + book.name + ", " + book.id + ", " +
book.price+'元'+','+book.address+","+book.isbn);
}
}
}
5、获取android的配置参数
对于插件开发,很多时候需要依赖其他插件,比如android插件开发,为了开发某些功能,我们需要不可避免的获取android gradle的配置参数和api,因此我们需要添加相应的依赖库到插件的build.gradle中
implementation 'com.android.tools.build:gradle:2.1.3'
插件类apply中,使用如下方式获取
def android = project.extensions.getByType(com.android.build.gradle.AppExtension)
android.applicationVariants.all{variant ->
println '::::>>> '+variant.buildType.name
println "applicationId: "+android.defaultConfig.applicationId
}
三、发布到远程Maven仓库
发布到远程maven仓库相对来说比较复杂,需要我们自己申请账号等一系列操作,这里我们暂时不写,以后补充。如果存在此类需求,可参考如下链接:
https://blog.youkuaiyun.com/pf_1308108803/article/details/78119591