I try to set up a Gradle Android Plugin to create buildTypes dynamically. The plugin is applied, I see it in the logs, but the finalizeDsl part is not triggered. Anyone knows why is that and how to fix it ?
I have followed https://github.com/android/gradle-recipes/tree/agp-9.0/addBuildTypeUsingDslFinalize to create the plugin.
Here is the plugin code:
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.gradle.AppPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.logging.LogLevel
import org.gradle.internal.cc.base.logger
class CustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
logger.log(LogLevel.INFO, "Logger CustomPlugin applied")
println("CustomPlugin applied")
project.afterEvaluate {
// Registers a callback on the application of the Android Application plugin.
// This allows the CustomPlugin to work whether it's applied before or after
// the Android Application plugin.
project.plugins.withType(AppPlugin::class.java) {
// Queries for the extension set by the Android Application plugin.
// This is the second of two entry points into the Android Gradle plugin
val androidComponents =
project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java)
androidComponents.finalizeDsl { extension ->
val stagingBuildType = extension.buildTypes.create("staging")
stagingBuildType.initWith(extension.buildTypes.getByName("debug"))
stagingBuildType.isDefault = true
val preprodBuildType = extension.buildTypes.create("preprod")
preprodBuildType.initWith(extension.buildTypes.getByName("release"))
logger.lifecycle("🔧 finalizeDsl running!") // Should appear in logs
println("CustomPlugin finalize called")
}
}
}
}
}
My build.gradle.kts:
plugins { `java-gradle-plugin` alias(libs.plugins.kotlin.jvm) } java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } } dependencies { compileOnly(libs.android.gradlePlugin.api) implementation(gradleKotlinDsl()) } gradlePlugin { plugins { create("addBuildTypeUsingDslFinalize") { id = "android.recipes.addBuildTypeUsingDslFinalize" implementationClass = "CustomPlugin" } } }
and the libs.versions.toml:
[versions] androidGradlePlugin = "8.13.2" kotlin = "2.1.20" [libraries] android-gradlePlugin-api = { group = "com.android.tools.build", name = "gradle-api", version.ref = "androidGradlePlugin" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
Take out the project.afterEvaluate.
override fun apply(project: Project) {
project.plugins.withType(AppPlugin::class.java) {
val androidComponents =
project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java)
androidComponents.finalizeDsl { extension ->
// your buildTypes code
}
}
}
Explanation:
AGP runs the finalizeDsl callbacks in its own afterEvaluate. When AGP is applied before your plugin, which is the usual order, its afterEvaluate run first. So by the time yours registers the callback, the DSL is already finalised, and it never runs.
The recipe registers it straight inside plugins.withType(AppPlugin::class.java), which already handles the plugin order.
Emmanuel Obiechina Ikenna