gradle系列——常用技巧(五)
什么是gradle插件
插件的概念可以说无处不在,例如chrome浏览器就有很多扩展插件,用来扩充网页的某种特定的功能,那gradle里面插件是用来干嘛的呢?
其实也一样,用来扩充某种特定的构建能力。gradle是一个构建框架,一定要注意他是一个框架,框架的作用就是定制规则,定制通用的模块,包括如何去管理项目的子模块,控制Task执行的生命周期等,但具体的构建任务,这个就比较多元化了,gradle不仅仅是给Android用的,java项目,web项目也都可以使用gradle去构建,所以针对不同的项目类型,不同的构建任务,gradle提供了插件这一接口,不同的构建任务对应成一个插件,在你需要的时候自己去引入,例如需要构建一个Apk,就引入Android的gradle插件
插件的使用
使用已有的插件主要有4个步骤
在项目build.gradle中引入插件的仓库,目的是告诉gradle,该项目的插件或者其他三方库可以去哪些仓库里面找
repositories {
// google这些都是gradle内部已经集成的,所以直接像调用方法一样引入
google()
mavenCentral()
声明导入具体的插件库,一个插件库中可能有多个插件
dependencies {
// 导入Android构建相关的插件库
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
在模块module中引入具体的插件
// 引入该插件,会引入打包Apk的一系列Task
apply plugin: 'com.android.application'
插件添加到模块module之后,一般会在当前project下添加两种能力,一种是用于配置的属性,一种是添加不同的Task
配置插件的属性,这个最常见的就是android闭包了,android闭包就是com.android.application这个插件提供的可配置的属性
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.myapplication"
minSdkVersion 19
targetSdkVersion 30
versionCode 1
versionName "1.0"
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
插件属性拓展——gradle DSL
上面android闭包这种代码看起来跟常规的语言不太一样,像是一种配置方式,但其实就是利用了闭包+delegate的方式实现的DSL,我们可以简单实现一个类似的
class Android {
private int mCompileSdkVersion
private String mBuildToolsVersion
private DefaultConfig mDefaultConfig = new DefaultConfig()
def compileSdkVersion(sdkVersion){
mCompileSdkVersion = sdkVersion
def buildToolsVersion(buildVersion){
mBuildToolsVersion = buildVersion
def defaultConfig(Closure closure){
closure.delegate = mDefaultConfig
closure.call()
class DefaultConfig {
private String mApplicationId
private int mMinSdkVersion
private int mTargetSdkVersion
def applicationId(appId){
mApplicationId = appId
def minSdkVersion(minVersion){
mMinSdkVersion = minVersion
def targetSdkVersion(targetVersion){
mTargetSdkVersion = targetVersion
def android(Closure closure){
Android android = new Android()
// 给闭包设置delegate
closure.delegate = android
closure.call()
// 调用android函数,就类似上面官方插件提供的android闭包的写法了
android {
compileSdkVersion 30
buildToolsVersion "30.0.1"
defaultConfig {
applicationId "com.dsl.android"
minSdkVersion 20
targetSdkVersion 30
自定义插件
我们自己也可以通过实现gradle提供的Plugin接口来实现自定义的插件
主要有3种创建插件的位置
直接在gradle脚本中
在buildSrc目录下
创建一个单独的工程
gradle脚本实现
这种方式很简单,例如在moudule的build.gradle文件中写一个插件
class MyPlugin implements Plugin<Project>{
@Override
void apply(Project project) {
println "MyPlugin hello"
// 然后可以直接在文件头部apply这个插件,在配置阶段执行到这行代码的时候实际上就会去执行上面重写的apply方法
apply plugin:MyPlugin
这种方式目前没找到实际的用处,意义不太大,了解即可
用buildSrc模块实现
当插件只在当前项目下使用时,可以使用这种方式
自定义插件
首先新建一个名为buildSrc的module(gradle会默认识别名为buildSrc的目录为项目的插件目录)
src目录下仅保留一个空的main文件夹,其他的全部删除,并在main文件夹下新建groovy文件夹和resources文件夹
在groovy文件夹下创建自定义的一个包名文件夹,例如com.tu.gradle.plugin,注意这个是创建了4层文件夹,然后在plugin文件下新建一个groovy文件CustomGradlePlugin.groovy,实现Plugin接口,并实现它的apply方法
class CustomGradlePlugin implements Plugin<Project>{
@Override
void apply(Project project) {
println "apply hello CustomGradlePlugin"
在resources目录下创建文件夹META-INF.gradle-plugins,注意是两层文件夹,然后在gradle-plugins文件夹下创建一个com.tu.gradle.plugin.properties文件,properties前的文件名部分跟前面创建的包名需要一致,该文件的作用是去指定插件的class
implementation-class=com.tu.gradle.plugin.CustomGradlePlugin
最后就可以在项目其他moudle中引入使用这个插件了,sync工程之后就能看到在配置阶段执行了自定义插件里apply函数里的代码
apply plugin: 'com.tu.gradle.plugin'
// 输出结果
> Configure project :app
apply hello CustomGradlePlugin
如果一个插件模块想写多个插件,是通过包名去区分的,不同的插件只需要放在不同的包下面
buildSrc的目录结构如图
增加配置属性
上面说了插件的主要功能是向当前project提供了配置属性和task,先自定义一个配置属性
在同一个包目录下新建一个VersionExtension.groovy文件,在里面定义一个实体类,这个实体类里面的属性就是向外提供的可配置属性
class VersionExtension {
String mVersionName
int mVersionCode
def versionName(name) {
mVersionName = name
def versionCode(code) {
mVersionCode = code
然后在我们的CustomGradlePlugin得apply方法中,把这个扩展配置属性添加到当前project当中
class CustomGradlePlugin implements Plugin<Project>{
@Override
void apply(Project project) {
println "apply hello CustomGradlePlugin"
// versionInfo是外部可使用的配置闭包名
project.extensions.create("versionInfo",VersionExtension.class)
这样就可以在引入该插件得模块脚本中去配置使用
versionInfo {
versionName "1.0.0"
versionCode 100
自定义Task
配置属性的最终目的是需要在插件的Task中去使用,下面在插件中自定义一个Task
同样在一个包目录下新建一个CustomPluginTask.groovy文件
class CustomPluginTask extends DefaultTask {
CustomPluginTask(){
// 指定Task得分组
group = "custom_plugin"
@TaskAction
void doAction(){
// 使用配置参数
def versionName = project.extensions.versionInfo.mVersionName
def versionCode = project.extensions.versionInfo.mVersionCode
println "custom plugin versionName is $versionName and versionCode is $versionCode"
然后在CustomGradlePlugin的Apply方法里,把创建的这个task添加到当前project中
class CustomGradlePlugin implements Plugin<Project>{
@Override
void apply(Project project) {
println "apply hello CustomGradlePlugin"
project.extensions.create("versionInfo",VersionExtension.class)
// customPluginTask是该Task的名称
project.tasks.create("customPluginTask",CustomPluginTask.class)
最后同步一下,当前module下就能看到这个customPluginTask
执行一下看看
> Task :app:customPluginTask
custom plugin versionName is 1.0.0 and versionCode is 100
到这,一个简单得自定义gradle插件就完成了,是不是很简单
有的博客说这种方式还要改builsSrc目录下的build.gradle文件,实践发现,这种方式根本就不需要build.gradle文件,我使用的gradle 6.7.1
使用这种方式主要就是供本项目使用,如果想要发布供其他项目使用的话,buildSrc是有一个坑点的,就是buildSrc模块属于是项目保留得一个模块,如果在setting.gradle中去include这个模块得话,就会报错
'buildSrc' cannot be used as a project name as it is a reserved name
但如果想要把插件发布得maven仓库,就必须把这个插件module include到setting.gradle脚本中,这样才能正常使用uploadArchives的task上传maven,所以使用这种方式的应用场景就是只在本项目直接使用(我实验是这样得,但看有得blog说可以,不知道是不是我操作有问题或者是gradle版本问题)
单独的gradle插件工程
这种方式跟在buildSrc模块的方式差不多,主要的区别在于插件module的build.gradle文件,需要去配置依赖的库,源码路径等信息,而且插件module可以任意取名(不能取名buildSrc),实际应用中推荐使用这种方式去做,可操作性比较强
apply plugin: 'groovy'
repositories {
mavenCentral()
dependencies {
implementation localGroovy()
implementation gradleApi()
sourceSets {
main{
groovy {
srcDir 'src/main/groovy'
resources {
srcDir 'src/main/resources'
把写的自定义插件发布成一个独立的库,这样可方便其他模块使用,发布可以分成两种,本地和远程
发布插件到本地
很简单,利用maven插件,在插件module的build.gradle中引入maven插件,并配置uploadArchives闭包
apply plugin: 'groovy'
apply plugin: 'maven'
repositories {
mavenCentral()
dependencies {
implementation localGroovy()
implementation gradleApi()
sourceSets {
main{
groovy {
srcDir 'src/main/groovy'
resources {
srcDir 'src/main/resources'
uploadArchives {
repositories.mavenDeployer {
repository(url: uri('../repo')) // 本地仓库路径
pom.groupId = "com.tu.gradle.plugin"// group唯一标识,可任意,通常为模块包名
pom.artifactId = "CustomGradlePlugin"// 插件项目名称,通常为插件库模块名称,可以任意,一个插件库中不同的插件通过不同的包名去区分
pom.version = "0.0.1"// 版本号
配置之后,sync下项目,就能在gradle视图的插件module中看到uploadArchives的task,运行这个task就能把插件发布到本地
发布插件到远程
跟发布插件到本地的差距就是配置相应的远程maven url及用户名密码
uploadArchives {
repositories.mavenDeployer {
repository(url: REMOTE_MAVEN_URL) { authentication(userName: "tu", password: "123456")
pom.groupId = "com.tu.gradle.plugin"// group唯一标识,可任意,通常为模块包名
pom.artifactId = "CustomGradlePlugin"// 插件项目名称,通常为插件库模块名称,可以任意,一个插件库中不同的插件通过不同的包名去区分
pom.version = "1.0.0"// 版本号
使用发布的插件
发布之后,就可以像平时使用三方插件一样去使用
先在根项目下声明引入插件
repositories {
// 本地maven相对地址
maven {
url 'repo'
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.tu.gradle.plugin:CustomGradlePlugin:1.0.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
然后在子module如app模块下使用
apply plugin: 'com.tu.gradle.plugin'
以上就是gradle插件相关知识的分享,如果有写的不对的地方欢迎批评指正,感觉写的还不错的也欢迎评论点赞支持一下