一文了解 Gradle 插件

Gradle 插件是一种扩展 Gradle 构建工具功能的组件,我们可以使用它来协助我们打包、测试等。在开发过程中,我们离不开插件,比如创建一个Android项目,就需要如下的插件。

kotlin 复制代码
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

Gradle 插件和任务(Task)的区别

Gradle 任务是构建过程中的一个具体动作或操作单元,类似于一个个具体的功能代码。而 Gradle 插件则是组装这些 Task 的集合,类似于 SDK。

简单来说,Gradle 插件包含多个 Gradle 任务;Gradle 插件的功能是由一个个任务完成的。

插件

插件的种类

插件分成三种:脚本插件(Script Plugins)、预编译脚本插件(Precompiled Script Plugins)、二进制插件(Binary Plugins)

  • 脚本插件,是指把代码写在构建脚本中,比如我们最熟悉的 build.gradle 文件
  • 预编译脚本插件,则是把代码放在一个 buildSrc 文件中,方便该项目的其他模块使用
  • 二进制插件,则是把代码打包成 jar 文件,供当前或者其他项目使用

自定义插件

上面提到过插件分为三种,它们之间的区别只是代码位置不同。为了体验插件编写和发布的全部流程,这里以二进制插件为例。首先我们先创建一个 module,如下图所示:

然后创建自己的插件类,我这里取名叫 MyPlugin,代码示例如下。可以看到,实现插件的功能很简单,我们只需要实现 Plugin 接口就可以了。

kotlin 复制代码
// 创建插件
class MyPlugin: Plugin<Project> {

    override fun apply(target: Project) {
        println("MyPlugin apply")
    }

}

然后在当前模块的 build.gradle 中使用 apply<MyPlugin>() 来应用插件,注意需要把这部分代码放在 build.gradle 文件的最前面。点击构建后,就可以看到插件的执行了。效果如下图所示:

从上图可以看到,gradle 的插件在被 apply 时就被运行。为了能参与后面的构建过程,我们一般在插件中注册任务,而不是在插件中直接执行逻辑操作。代码示例如下:

kotlin 复制代码
class MyPlugin : Plugin<Project> {

    override fun apply(target: Project) {
        println("MyPlugin apply")
        // 注册任务,执行操作
        target.tasks.register("myTask") {
            it.doLast {
                println("do something")
            }
        }
    }
}

自定义插件配置扩展

在Android中,我们常常看到如下的配置参数,这些都是Android插件构建需要的配置。

kotlin 复制代码
android {
    namespace = "com.example.demo"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.demo"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
    ...
}    

如果你想要仿照Android的插件,也为自己的插件加上配置参数,可以定义如下的配置类。注意,class 必须是 open 的

kotlin 复制代码
open class MyExtension {

    var tag: String? = null
    var user: MyUser? = null

    constructor(project: Project) {
        user = project.extensions.create("user", MyUser::class.java)
    }

}
// 嵌套的配置
open class MyUser {
    var name: String? = null
    var age: String? = null
}

然后在插件中注册并获取对应的配置,代码示例如下:

kotlin 复制代码
class MyPlugin : Plugin<Project> {

    override fun apply(target: Project) {
        println("MyPlugin apply")
        val extension = target.extensions.create("my_extension", MyExtension::class.java)
        target.tasks.register("fetchextension") {
            it.doLast {
                println("extension tag = ${extension.tag}")
                println("name: ${extension.user?.name} age: ${extension.user?.age}")
            }
        }
    }
}

完成这些步骤后,我们就可以在 build.gradle 中的配置如下:

ini 复制代码
my_extension {
    tag = "test_tag"
    user {
        name = "test_name"
        age = "test_age"
    }
}

注意;apply<MyPlugin>() 在 kotlin 脚本中有点问题,一直报获取不了自定义插件配置扩展的错误,需要本地发布依赖才能正常拉取配置。而同样的代码逻辑在 groovy 脚本中,使用 apply plugin 是没有问题的

打包

要想我们编写的二进制插件打包,需要先设置如下配置:

bash 复制代码
plugins {
    id("java-gradle-plugin")
    id("org.jetbrains.kotlin.jvm")
}

gradlePlugin {
    plugins{
        create("myPlugin") {
            id = "com.example.plugin.MyPlugin"
            implementationClass = "com.demo.plugin.MyPlugin"
        }
    }
}

其中,id 是插件的唯一标识,就是我们应用插件时设置的,比如应用android插件 id("org.jetbrains.kotlin.android")implementationClass 则是我们插件的实现类的路径。完成这边步骤后,我们就可以对编写完成的插件进行发布了。

插件发布

插件发布分为本地发布和远端发布两种,下面将分别介绍。

本地发布

本地发布,顾名思义就是把打包的jar发布到本地仓库。要想实现这个功能,我们需要先在当前模块的 build.gradle 中设置如下依赖,并设置配置项。

kotlin 复制代码
id("maven-publish")

publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            groupId = "com.example.plugin"
            artifactId = "MyPlugin"
            version = "1.0.0"
            from(components["java"])
        }
    }

    // 配置仓库
    repositories {
        maven {
            name = "localPluginRepository"
            url = uri("../local-plugin-repository")
        }
    }
}


dependencies {
    implementation("com.android.tools.build:gradle:7.3.1")
}

执行 ./gradlew publish 命令后,就可以在本地仓库看到发布成的包了。

如果我们想要在项目中使用这个包,需要在 setting.gradle 中设置本地仓库的位置,代码如下所示:

scss 复制代码
pluginManagement {
    repositories {
        maven {
            // 设置本地仓库的路径
            setUrl("./local-plugin-repository")
        }
        google {
            content {
                includeGroupByRegex("com\.android.*")
                includeGroupByRegex("com\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
    plugins {
        kotlin("jvm") version "2.0.0"
    }
}

同时在项目根目录中,依赖这个插件

scss 复制代码
buildscript {
    dependencies {
        classpath("com.example.plugin:MyPlugin:1.0.0")
    }
}

最后就可以在 build.gradle 中 apply 并配置 my_extension 的属性了。

kotlin 复制代码
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.jetbrains.kotlin.android)
    id("com.example.plugin.MyPlugin")
}


android {
   ...
}


my_extension {
    tag = "test_tag"
    user {
        name = "test_name"
        age = "test_age"
    }
}

远端发布

远端发布流程可以看 Yechaoa 大佬的 【Gradle-9】Gradle插件发布指南。这篇文章已经讲得很详细了,我就不重复介绍了。

参考

相关推荐
花生糖@1 小时前
Android XR 应用程序开发 | 从 Unity 6 开发准备到应用程序构建的步骤
android·unity·xr·android xr
是程序喵呀1 小时前
MySQL备份
android·mysql·adb
casual_clover1 小时前
Android 之 List 简述
android·list
锋风Fengfeng2 小时前
安卓15预置第三方apk时签名报错问题解决
android
User_undefined3 小时前
uniapp Native.js原生arr插件服务发送广播到uniapp页面中
android·javascript·uni-app
程序员厉飞雨4 小时前
Android R8 耗时优化
android·java·前端
丘狸尾5 小时前
[cisco 模拟器] ftp服务器配置
android·运维·服务器
van叶~7 小时前
探索未来编程:仓颉语言的优雅设计与无限可能
android·java·数据库·仓颉
Crossoads11 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
li_liuliu12 小时前
Android4.4 在系统中添加自己的System Service
android