了解如何创建和使用自定义 Gradle 插件
什么是约定插件
约定插件是一种组织 Gradle 文件的结构化方法,可作为 Gradle 模块中的一个插件使用。
优点
可重复使用: 插件可在多个 Gradle 模块中重复使用,从而提高一致性和效率。
易于维护: 复杂的构建逻辑可通过扩展或组合其他构建逻辑来开发,并可封装到专用插件(如 ArtifactDeploymentPlugin、AndroidLibraryPlugin 和 AndroidComposePlugin 等)中,以方便使用。
易于使用: 通过应用插件,用户可以轻松地为其构建流程添加新功能,而无需再次从头开始编写复杂的代码。
可测试的构建逻辑: 可使用 TestKit 测试构建逻辑,以验证其行为。(尚未尝试)
怎么添加约定插件
第一步:创建 build-logic 目录
- 创建一个单独的
build-logic文件夹来整理你的约定插件代码,并将其与其他项目代码分开。 - 在根目录下,创建一个
settings.gradle.kts文件,内容如下:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml")) // Create this file if not present.
}
}
}
rootProject.name = "build-logic"
// include(":convention") // Enable this line only after step 2
在项目的 settings.gradle.kts 内,将 includeBuild(“build-logic”) 添加到 pluginManagement 块中。
pluginManagement {
includeBuild("build-logic") // Include the build-logic
repositories {
// ...
gradlePluginPortal()
}
}
// ...
第二步:创建构建约定模块
- 在
build-logic下添加一个新的 Java/Kotlin 模块,并将其命名为convention。在此示例中,包名称为com.droidstarter.convention。 - 确保删除根
settings.gradle.kts文件中任何类似include(“:build-logic:convention”)的条目(当创建新模块时,Studio 会自动添加此条目)。 - 将
convention模块中的脚本替换为:
plugins {
`kotlin-dsl`
}
group = "com.example.buildlogic" // Package name for the our plugins
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependencies {
compileOnly(libs.android.gradlePlugin)
compileOnly(libs.kotlin.gradlePlugin)
}
gradlePlugin {
plugins {
// Will add in next step
}
}
将以下依赖项添加到 libs.versions.toml :
[versions]
androidGradlePlugin = "8.0.2" # use latest version
kotlin = "1.9.22" # use latest version
[libraries]
android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" }
kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
在 build-logic 模块的 settings.gradle.kts 文件中添加 include(“:convention”) ,然后执行 Gradle 同步。
第三步:创建自定义 Gradle 约定插件
- 首先,设置一个名为
AndroidApplicationComposeConventionPlugin的基本约定插件。此插件将集中设置一个使用 Jetpack Compose 的 Android 项目所需的所有构建配置。 - 使用
Plugin<Project>来定义和应用自定义配置。
class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
println("*** AndroidApplicationComposeConventionPlugin invoked ***")
// Additional configuration here...
}
}
- 在 build-logic 的
build.gradle.kts中注册插件,使其可在其他模块中使用:
plugins {
`kotlin-dsl`
}
// ...
gradlePlugin {
plugins {
create("androidApplicationCompose") {
id = "com.example.convention.application.compose" // This is the id we used to resolve our plugin.
implementationClass = "com.example.convention.AndroidApplicationComposeConventionPlugin"
}
}
}
- 将新创建的插件应用到你的
app模块或任何 Android 应用模块。
plugins {
id("com.example.convention.application.compose")
}
- 执行 Gradle 同步,你现在应该在构建窗口中看到以下日志:
**** AndroidApplicationComposeConventionPlugin invoked ****
第四步:为使用 Jetpack Compose 构建逻辑的 Android 应用配置插件
- 在你的约定插件中应用 Android 和 Kotlin 插件,这样当该插件被应用时,这些插件会自动被包含进来。这使你可以从应用模块的
build.gradle.kts中移除它们。
class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
println("*** AndroidApplicationComposeConventionPlugin invoked ***")
with(target) {
with(pluginManager) {
apply("com.android.application") // Include android application plugin
apply("org.jetbrains.kotlin.android") // Ensure project build.gradle declared this plugin
}
}
}
}
- 配置常见的设置,如
compileSdk,minSdk,targetSdk,sourceCompatibility,targetCompatibility, 和kotlinJvmTarget - 设置 Jetpack Compose 配置,包括启用 Compose 功能和添加必要的依赖项。
class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
apply("com.android.application")
apply("org.jetbrains.kotlin.android") // Ensure project build.gradle declared this plugin
val extensions = extensions.getByType<ApplicationExtension>()
configureAndroidCompose(extensions)
}
}
}
internal fun Project.configureAndroidCompose(commonExtension: CommonExtension<*, *, *, *, *, *>) {
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
commonExtension.apply {
compileSdk = 36
defaultConfig {
minSdk = 29
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildFeatures {
compose = true
}
composeOptions {
// Add androidxComposeCompiler in toml
kotlinCompilerExtensionVersion = libs.findVersion("androidxComposeCompiler").get().toString()
}
dependencies {
val bom = libs.findLibrary("androidx-compose-bom").get()
add("implementation", platform(bom))
listOf(
"androidx.core.ktx",
"androidx.lifecycle.runtime.ktx",
"androidx.activity.compose",
"androidx.ui",
"androidx.ui.graphics",
"androidx.ui.tooling.preview",
"androidx.material3",
// "material.icons.extended"
).forEach { alias ->
add("implementation", libs.findLibrary(alias).get())
}
add("testImplementation", libs.findLibrary("junit").get())
add("androidTestImplementation", libs.findLibrary("androidx.junit").get())
add("androidTestImplementation", libs.findLibrary("androidx.espresso.core").get())
add("androidTestImplementation", platform(bom))
add("androidTestImplementation", libs.findLibrary("androidx.ui.test.junit4").get())
add("androidTestImplementation", libs.findLibrary("androidx.ui.tooling").get())
add("androidTestImplementation", libs.findLibrary("androidx.ui.test.manifest").get())
}
}
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}
}
- 将以下依赖项添加到
libs.versions.toml:
[versions]
androidxComposeCompiler = "1.5.10" # use latest version
androidxComposeBom = "2024.02.01" # use latest version
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" }