Skip to content
Draft

AGP 9 #1959

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d46b9dc
🚧 AGP 9
SimonMarquis Aug 31, 2025
9908869
android.newDsl=false
SimonMarquis Sep 14, 2025
a0ad925
`devices` is deprecated in `managedDevices`
SimonMarquis Sep 14, 2025
fd939d5
Move internal modifier to the object to work around build errors
SimonMarquis Sep 14, 2025
80bee3d
Add explicit junit dependency on Android library modules
SimonMarquis Sep 21, 2025
ee84562
9.0.0-alpha10
SimonMarquis Oct 12, 2025
dbce15c
9.0.0-alpha12
SimonMarquis Oct 28, 2025
f1043ef
KSP 2.3.0
SimonMarquis Oct 28, 2025
61d7a3b
9.0.0-alpha13
SimonMarquis Oct 31, 2025
fb4a5ca
KSP 2.3.1-SNAPSHOT
SimonMarquis Oct 31, 2025
df589f6
Firebase Perf fix
SimonMarquis Oct 31, 2025
1ea5c39
Merge remote-tracking branch 'origin/main' into agp-9
SimonMarquis Nov 6, 2025
ece169e
build-tools 32.0.0-alpha13
SimonMarquis Nov 6, 2025
4312937
Remove maven repository for snapshots
SimonMarquis Nov 6, 2025
3bc6ed6
9.0.0-alpha14
SimonMarquis Nov 7, 2025
b060fd0
Replace API breaking changes
SimonMarquis Nov 7, 2025
52b118a
Prevent Jacoco convention plugins to enable test coverage on release …
SimonMarquis Nov 7, 2025
1ebc99d
Clarify Jacoco configuration for debug build
SimonMarquis Nov 10, 2025
06fe669
Remove VisibleForTesting
SimonMarquis Nov 10, 2025
1e7095d
Revert AGP's APIs change workarounds with `.apply{}` to reduce visual…
SimonMarquis Nov 11, 2025
354261e
Merge branch 'main' into agp-9
SimonMarquis Nov 14, 2025
e420d2b
9.0.0-beta01
SimonMarquis Nov 14, 2025
919831c
9.0.0-beta02
SimonMarquis Nov 22, 2025
113cc2a
9.0.0-beta03
SimonMarquis Nov 29, 2025
269f445
Merge remote-tracking branch 'origin/main' into agp-9
SimonMarquis Dec 10, 2025
12c265c
9.0.0-beta04
SimonMarquis Dec 10, 2025
7af1c8b
Fix warnings on changed files
SimonMarquis Dec 10, 2025
10a3b62
9.0.0-beta05
SimonMarquis Dec 11, 2025
7dffc31
`android.disallowKotlinSourceSets=false`
SimonMarquis Dec 11, 2025
21d2df8
9.0.0-rc01
SimonMarquis Dec 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build-logic/convention/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ kotlin {
}

dependencies {
compileOnly(libs.android.gradleApiPlugin)
compileOnly(libs.android.gradlePlugin)
compileOnly(libs.android.tools.common)
compileOnly(libs.compose.gradlePlugin)
compileOnly(libs.firebase.crashlytics.gradlePlugin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.google.samples.apps.nowinandroid.configureBadgingTasks
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
Expand All @@ -30,20 +31,18 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
apply(plugin = "com.android.application")
apply(plugin = "org.jetbrains.kotlin.android")
apply(plugin = "nowinandroid.android.lint")
apply(plugin = "com.dropbox.dependency-guard")

extensions.configure<ApplicationExtension> {
configureKotlinAndroid(this)
defaultConfig.targetSdk = 36
@Suppress("UnstableApiUsage")
testOptions.animationsDisabled = true
configureGradleManagedDevices(this)
}
extensions.configure<ApplicationAndroidComponentsExtension> {
configurePrintApksTask(this)
configureBadgingTasks(extensions.getByType<ApplicationExtension>(), this)
configureBadgingTasks(extensions.getByType<CommonExtension>(), this)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,16 @@ import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
import org.gradle.testing.jacoco.plugins.JacocoPlugin

class AndroidApplicationJacocoConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
apply(plugin = "jacoco")

val androidExtension = extensions.getByType<ApplicationExtension>()

androidExtension.buildTypes.configureEach {
enableAndroidTestCoverage = true
enableUnitTestCoverage = true
}

configureJacoco(extensions.getByType<ApplicationAndroidComponentsExtension>())
apply<JacocoPlugin>()
configureJacoco(
commonExtension = extensions.getByType<ApplicationExtension>(),
androidComponentsExtension = extensions.getByType<ApplicationAndroidComponentsExtension>(),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,12 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
apply(plugin = "com.android.library")
apply(plugin = "org.jetbrains.kotlin.android")
apply(plugin = "nowinandroid.android.lint")

extensions.configure<LibraryExtension> {
configureKotlinAndroid(this)
testOptions.targetSdk = 36
lint.targetSdk = 36
defaultConfig.targetSdk = 36
defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testOptions.animationsDisabled = true
configureFlavors(this)
Expand All @@ -57,6 +55,7 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
dependencies {
"androidTestImplementation"(libs.findLibrary("kotlin.test").get())
"testImplementation"(libs.findLibrary("kotlin.test").get())
"testImplementation"(libs.findLibrary("junit").get())

"implementation"(libs.findLibrary("androidx.tracing.ktx").get())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,16 @@ import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
import org.gradle.testing.jacoco.plugins.JacocoPlugin

class AndroidLibraryJacocoConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
apply(plugin = "jacoco")

val androidExtension = extensions.getByType<LibraryExtension>()

androidExtension.buildTypes.configureEach {
enableAndroidTestCoverage = true
enableUnitTestCoverage = true
}

configureJacoco(extensions.getByType<LibraryAndroidComponentsExtension>())
apply<JacocoPlugin>()
configureJacoco(
commonExtension = extensions.getByType<LibraryExtension>(),
androidComponentsExtension = extensions.getByType<LibraryAndroidComponentsExtension>(),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class AndroidTestConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
apply(plugin = "com.android.test")
apply(plugin = "org.jetbrains.kotlin.android")

extensions.configure<TestExtension> {
configureKotlinAndroid(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginE
* Configure Compose-specific options
*/
internal fun Project.configureAndroidCompose(
commonExtension: CommonExtension<*, *, *, *, *, *>,
commonExtension: CommonExtension,
) {
commonExtension.apply {
buildFeatures {
buildFeatures.apply {
compose = true
}

Expand All @@ -46,6 +46,7 @@ internal fun Project.configureAndroidCompose(
extensions.configure<ComposeCompilerGradlePluginExtension> {
fun Provider<String>.onlyIfTrue() = flatMap { provider { it.takeIf(String::toBoolean) } }
fun Provider<*>.relativeToRootProject(dir: String) = map {
@Suppress("UnstableApiUsage")
isolated.rootProject.projectDirectory
.dir("build")
.dir(projectDir.toRelativeString(rootDir))
Expand All @@ -59,6 +60,7 @@ internal fun Project.configureAndroidCompose(
.relativeToRootProject("compose-reports")
.let(reportsDestination::set)

@Suppress("UnstableApiUsage")
stabilityConfigurationFiles
.add(isolated.rootProject.projectDirectory.file("compose_compiler_config.conf"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package com.google.samples.apps.nowinandroid

import com.android.SdkConstants
import com.android.build.api.artifact.SingleArtifact
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.google.common.truth.Truth.assertWithMessage
import org.gradle.api.DefaultTask
Expand Down Expand Up @@ -110,7 +110,7 @@ private fun String.capitalized() = replaceFirstChar {
}

fun Project.configureBadgingTasks(
baseExtension: ApplicationExtension,
baseExtension: CommonExtension,
componentsExtension: ApplicationAndroidComponentsExtension,
) {
// Registers a callback to be called, when a new variant is configured
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.gradle.kotlin.dsl.invoke
* Configure project for Gradle managed devices
*/
internal fun configureGradleManagedDevices(
commonExtension: CommonExtension<*, *, *, *, *, *>,
commonExtension: CommonExtension,
) {
val pixel4 = DeviceConfig("Pixel 4", 30, "aosp-atd")
val pixel6 = DeviceConfig("Pixel 6", 31, "aosp")
Expand All @@ -34,9 +34,11 @@ internal fun configureGradleManagedDevices(
val allDevices = listOf(pixel4, pixel6, pixelC)
val ciDevices = listOf(pixel4, pixelC)

commonExtension.testOptions {

commonExtension.testOptions.apply {
@Suppress("UnstableApiUsage")
managedDevices {
devices {
allDevices {
allDevices.forEach { deviceConfig ->
maybeCreate(deviceConfig.taskName, ManagedVirtualDevice::class.java).apply {
device = deviceConfig.device
Expand All @@ -48,7 +50,7 @@ internal fun configureGradleManagedDevices(
groups {
maybeCreate("ci").apply {
ciDevices.forEach { deviceConfig ->
targetDevices.add(devices[deviceConfig.taskName])
targetDevices.add(localDevices[deviceConfig.taskName])
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package com.google.samples.apps.nowinandroid

import com.android.build.api.artifact.ScopedArtifact
import com.android.build.api.dsl.BuildType
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.variant.AndroidComponentsExtension
import com.android.build.api.variant.ScopedArtifacts
import com.android.build.api.variant.SourceDirectories
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.file.Directory
import org.gradle.api.file.RegularFile
Expand Down Expand Up @@ -59,8 +62,15 @@ private fun String.capitalize() = replaceFirstChar {
* tests on CI using a different Github Action or an external device farm.
*/
internal fun Project.configureJacoco(
commonExtension: CommonExtension,
androidComponentsExtension: AndroidComponentsExtension<*, *, *>,
) {
// Configure only the debug build, otherwise it will force the debuggable flag on release buildTypes as well
commonExtension.buildTypes.named("debug") {
enableAndroidTestCoverage = true
enableUnitTestCoverage = true
}

configure<JacocoPluginExtension> {
toolVersion = libs.findVersion("jacoco").get().toString()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
* Configure base Kotlin with Android options
*/
internal fun Project.configureKotlinAndroid(
commonExtension: CommonExtension<*, *, *, *, *, *>,
commonExtension: CommonExtension,
) {
commonExtension.apply {
compileSdk = 36

defaultConfig {
defaultConfig.apply {
minSdk = 23
}

compileOptions {
compileOptions.apply {
// Up to Java 11 APIs are available through desugaring
// https://developer.android.com/studio/write/java11-minimal-support-table
sourceCompatibility = JavaVersion.VERSION_11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@ enum class NiaFlavor(val dimension: FlavorDimension, val applicationIdSuffix: St
}

fun configureFlavors(
commonExtension: CommonExtension<*, *, *, *, *, *>,
commonExtension: CommonExtension,
flavorConfigurationBlock: ProductFlavor.(flavor: NiaFlavor) -> Unit = {},
) {
commonExtension.apply {
FlavorDimension.values().forEach { flavorDimension ->
flavorDimensions += flavorDimension.name
}

productFlavors {
productFlavors.apply flavors@{
NiaFlavor.values().forEach { niaFlavor ->
register(niaFlavor.name) {
dimension = niaFlavor.dimension.name
flavorConfigurationBlock(this, niaFlavor)
if (this@apply is ApplicationExtension && this is ApplicationProductFlavor) {
if (this@flavors is ApplicationExtension && this is ApplicationProductFlavor) {
if (niaFlavor.applicationIdSuffix != null) {
applicationIdSuffix = niaFlavor.applicationIdSuffix
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object DataStoreModule {

@Provides
@Singleton
internal fun providesUserPreferencesDataStore(
fun providesUserPreferencesDataStore(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change needed? Is it related to the AGP upgrade?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, see this commit: fd939d5

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a bug, please file one. Potentially a hilt issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably due to mangling. Unfortunate I'm be afk for a few weeks and I won't be able to create a proper bug report until I'm back.

@ApplicationContext context: Context,
@Dispatcher(IO) ioDispatcher: CoroutineDispatcher,
@ApplicationScope scope: CoroutineScope,
Expand Down
5 changes: 5 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,8 @@ roborazzi.test.verify=true
# Prevent uninstall app after instrumented tests
# https://issuetracker.google.com/issues/295039976
android.injected.androidTest.leaveApksInstalledAfterRun=true

android.newDsl=false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment on why we need to opt out linking to the hilt bug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not meant to be merged as-is, as mentioned in the PR first message.
That being said, if you really want to merge this PR before alls bugs are fixed & workarounds are removed, I can add a comment for this. Let me know.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a link to the issue.


# Temporary suppresson of androidx.baselineprofile plugin issue (now flagged as error by AGP beta05)
android.disallowKotlinSourceSets=false
7 changes: 4 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
accompanist = "0.37.0"
androidDesugarJdkLibs = "2.1.4"
# AGP and tools should be updated together
androidGradlePlugin = "8.13.1"
androidTools = "31.13.1"
androidGradlePlugin = "9.0.0-rc01"
androidTools = "32.0.0-rc01"
androidxActivity = "1.9.3"
androidxAppCompat = "1.7.0"
androidxBrowser = "1.8.0"
Expand Down Expand Up @@ -134,6 +134,7 @@ hilt-core = { group = "com.google.dagger", name = "hilt-core", version.ref = "hi
hilt-ext-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltExt" }
hilt-ext-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltExt" }
javax-inject = { module = "javax.inject:javax.inject", version = "1" }
junit = { module = "junit:junit", version.ref = "junit4" }
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlin" }
kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
Expand All @@ -160,7 +161,7 @@ truth = { group = "com.google.truth", name = "truth", version.ref = "truth" }
turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" }

# Dependencies of the included build-logic
android-gradleApiPlugin = { group = "com.android.tools.build", name = "gradle-api", version.ref = "androidGradlePlugin" }
android-gradlePlugin = { group = "com.android.tools.build", name = "gradle-api", version.ref = "androidGradlePlugin" }
android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" }
compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
firebase-crashlytics-gradlePlugin = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "firebaseCrashlyticsPlugin" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ abstract class SyncModule {
syncSubscriber: FirebaseSyncSubscriber,
): SyncSubscriber

companion object {
internal companion object {
@Provides
@Singleton
internal fun provideFirebaseMessaging(): FirebaseMessaging = Firebase.messaging
fun provideFirebaseMessaging(): FirebaseMessaging = Firebase.messaging
}
}