gradle之:自定义插件
一.自定义插件(plugin)的目的
插件是一个gradle的扩展,这里思考一个问题,有了task之后,为什么还需要自定义插件?
这里我认为自定义插件是为了组合一系列task,提供更高颗粒度的复用能力。
并且gradle plugin还可以包在jar包或者aar中发布到远程仓库
二.自定义插件的步骤
2.1 自定义插件的方式
新建plugin的模块有两种方式,独立发布插件和简化插件。
简化插件的定义利用了gradle自动识别buildSrc目录的特征,将自定义插件放置到buildSrc目录下,它的缺点是无法发布到远程被复用。
独立发布插件方式步骤与简化方式基本一致,但是可以发布到远程maven仓库
2.1.1 简化方式定义插件
新建一个文件夹命名为buildSrc,同时在这个目录下新建build.gradle,注意名字和大小写必须完全一致,gradle在启动时会在配置阶段自动扫描buildSrc目录,并配置buildSrc下的build.gradle。
在buildSrc下新建两个目录
src/main/groovy
src/main/java
然后在build.gradle中添加对应的plugin插件
buildscript { repositories { google() jcenter() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:4.1.2' } } //识别groovy 插件 apply plugin : "groovy" apply plugin: "java" repositories { mavenCentral() } dependencies { }复制代码
其中:
apply plugin : "groovy" apply plugin: "java"复制代码
当添加这两行后,你会发现android studio会将groovy目录和java目录转变成蓝色表示已经识别到了,也可以只添加一种比如groovy或者java目录,这样,我们实现插件的语言就根据自己选择的plugin转换,一般建议用groovy更加高效简洁。
2.1.1 独立发布方式定义插件
新建一个java模块,命名为plugins,同样新建目录src/main/groovy,名字不需要固定,在plugins目录下添加build.gradle,
plugins { id 'groovy' } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) //我们需要实现gradle的Plugin<T>接口,来做自定义插件,因此依赖gradle api implementation gradleApi() //依赖gradle提供的groovy sdk,在编写自定义插件的时候,用groovy更快。 implementation localGroovy() }复制代码
这里与简化方式的区别在于需要在dependencies下添加依赖
implementation gradleApi() implementation localGroovy()复制代码
2.2 申明配置plugin
这个步骤作用在于申明定义的plugin的名字,方便我们依赖插件。
在src目录下新建resources/META-INF/gradle-plugins目录,在这个目录下新建xxx.xxx.xxx.properties文件,这个xxx,代表的是不包含类名的插件的完整包路径,如com.hch.bsDiff下的BsDiffPlugin,我们生成的properties文件为com.hchbsDiff.properties,里面的内容为
implementation-class=com.hch.plugin.BsDiffPlugin复制代码
2.3 自定义plugin
自定义plugin是真正做事的地方,一般一个plugin与一个任务对应,通过继承自plugin来定义一个插件
class BsDiffPlugin implements Plugin<Project>{ @Override void apply(Project project) { project.afterEvaluate { //只是定义任务,不会执行,执行还需要手动 ./gradlew bsDiff project.task(type:BsDiffTask , "bsDiff"){ inputs.files "${project.rootDir.absolutePath}/temp/testold.txt","${project.rootDir.absolutePath}/temp/testnew.txt" outputs.files "${project.rootDir.absolutePath}/temp/testdiff.patch" } } } }复制代码
在gradle的配置阶段,plugin的apply方法会被执行,一般在这个方法里面,我们会关联一个task,并将关联的task的参数传递进去,通过project参数,我们能拿到与构建流程相关的所有信息。
这里我们定义了一个BsDiffPlugin插件,同时生成一个bsDiffTask。
2.4 定义插件关联的任务
BsDiffTask
class BsDiffTask extends DefaultTask{ //外部生成任务的时候,会修改 project.task(type:com.hch.plugin.BsDiffTask , "bsDiffWrapper") BsDiffTask(){ group "差分任务" description "bsDiff" } @TaskAction void diff(){ println "start diff...." File fileOld = inputs.files.files[0]; File fileNew = inputs.files.files[1]; File diff = outputs.files.files[0]; BSDiff.bsdiff(fileOld , fileNew , diff); println "end diff...." } }复制代码
2.5 使用自定义的插件
2.5.1 简化插件依赖
如果是简化插件,我们仅需要在项目app中的build.gradle中通过两种方式使用自定义插件
//方式一 plugins{ id 'com.hch.plugin.bsDiff' } //方式二 apply plugin: BsDiffPlugin复制代码
这里的id就是properties的名字
2.5.2 独立插件依赖
如果是独立的插件,还需要添加plugin的依赖
在根目录的build.gradle中添加
buildscript{ repositories{ //... //指定一个maven仓库的路径 maven { url "xxxxx" } } dependencies{ //... classpath('com.hch.bsdiff:BsDiffPlugin') } }复制代码
同时也需要在app下的build.gradle中增加
//方式一 plugins{ id 'com.hch.plugin.bsDiff' } //方式二 apply plugin: BsDiffPlugin复制代码
2.5.3 使用插件中的任务
插件被依赖到项目中后,我们就可以使用插件中的任务了
afterEvaluate { println "assembleRelease === ${assembleRelease}" assembleRelease.finalizedBy 'bsDiff' }
作者:八道
链接:https://juejin.cn/post/7021729648480354311