一文了解 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插件发布指南。这篇文章已经讲得很详细了,我就不重复介绍了。

参考

相关推荐
雨白5 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹7 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空8 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭9 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日10 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安10 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑10 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟14 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡15 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0015 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体