fix(deps): update android.gradle.plugin to v9 (major) (#6021)

* Update android.gradle.plugin to v9

* Separate extensions between app and library ones

`CommonExtension` has been split and its properties are now duplicated in `ApplicationExtension` and `LibraryExtension` without a shared interface, so we now need to duplicate the helper extension functions

* Bump Gradle wrapper to `9.3.1`

* Remove `kotlin-android` plugin usage: it's no longer needed

* Enable `resValues` build feature for the modules that have resources in custom variants like gplay, debug, etc.

Otherwise this now fails saying the resources are there but the feature is disabled

* Remove `retrofit` dependency from `:features:call:impl`

It wasn't in use and the build was failing

* Update kotlin to v2.4.0

* Update plugin paparazzi to v2.0.0-alpha05

* Update gradle wrapper to 9.5.1

./gradlew wrapper --gradle-version 9.5.1 --gradle-distribution-sha256-sum bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f

* Update com.android.tools.build:gradle to 9.2.1

* Update plugin sonarqube to v7.3.1.8318

* Kotlin 2.4.0

* Context parameters are enabled by default in Kotlin 2.4.0

* Fix code issue

* Fix record screenshot issue

* Workaround for https://github.com/cashapp/paparazzi/issues/2342

* Workaround for another issue with Paparazzi

* Remove unused import

* Update screenshots

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jorge Martín <jorgem@element.io>
Co-authored-by: Benoit Marty <benoitm@element.io>
Co-authored-by: Benoit Marty <benoit@matrix.org>
Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
renovate[bot]
2026-06-11 09:51:47 +02:00
committed by GitHub
parent 37fed3e8fe
commit f0a6cba6db
165 changed files with 464 additions and 365 deletions
+1 -1
View File
@@ -2,6 +2,6 @@
<project version="4"> <project version="4">
<component name="KotlinJpsPluginSettings"> <component name="KotlinJpsPluginSettings">
<option name="externalSystemId" value="Gradle" /> <option name="externalSystemId" value="Gradle" />
<option name="version" value="2.3.21" /> <option name="version" value="2.4.0" />
</component> </component>
</project> </project>
+1 -1
View File
@@ -28,7 +28,6 @@ import java.util.Locale
plugins { plugins {
id("io.element.android-compose-application") id("io.element.android-compose-application")
alias(libs.plugins.kotlin.android)
// When using precompiled plugins, we need to apply the firebase plugin like this // When using precompiled plugins, we need to apply the firebase plugin like this
id(libs.plugins.firebaseAppDistribution.get().pluginId) id(libs.plugins.firebaseAppDistribution.get().pluginId)
id("kotlin-parcelize") id("kotlin-parcelize")
@@ -189,6 +188,7 @@ android {
buildFeatures { buildFeatures {
buildConfig = true buildConfig = true
resValues = true
} }
flavorDimensions += "store" flavorDimensions += "store"
productFlavors { productFlavors {
-2
View File
@@ -106,8 +106,6 @@ allprojects {
// Fix compilation warning for annotations // Fix compilation warning for annotations
// See https://youtrack.jetbrains.com/issue/KT-73255/Change-defaulting-rule-for-annotations for more details // See https://youtrack.jetbrains.com/issue/KT-73255/Change-defaulting-rule-for-annotations for more details
freeCompilerArgs.add("-Xannotation-default-target=first-only") freeCompilerArgs.add("-Xannotation-default-target=first-only")
// Opt-in to context receivers
freeCompilerArgs.add("-Xcontext-parameters")
} }
} }
} }
-1
View File
@@ -84,7 +84,6 @@ dependencies {
implementation(projects.services.toolbox.api) implementation(projects.services.toolbox.api)
implementation(libs.androidx.webkit) implementation(libs.androidx.webkit)
implementation(libs.coil.compose) implementation(libs.coil.compose)
implementation(libs.network.retrofit)
implementation(libs.serialization.json) implementation(libs.serialization.json)
implementation(libs.element.call.embedded) implementation(libs.element.call.embedded)
api(projects.features.call.api) api(projects.features.call.api)
+4 -4
View File
@@ -3,9 +3,9 @@
[versions] [versions]
# Project # Project
android_gradle_plugin = "8.13.2" android_gradle_plugin = "9.2.1"
# When updating this, please also update the version in the file ./idea/kotlinc.xml # When updating this, please also update the version in the file ./idea/kotlinc.xml
kotlin = "2.3.21" kotlin = "2.4.0"
kotlinpoet = "2.3.0" kotlinpoet = "2.3.0"
ksp = "2.3.9" ksp = "2.3.9"
firebaseAppDistribution = "5.2.1" firebaseAppDistribution = "5.2.1"
@@ -269,11 +269,11 @@ ktlint = "org.jlleitschuh.gradle.ktlint:14.2.0"
dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12" dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12"
dependencycheck = "org.owasp.dependencycheck:12.2.2" dependencycheck = "org.owasp.dependencycheck:12.2.2"
dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" } dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" }
paparazzi = "app.cash.paparazzi:2.0.0-alpha04" paparazzi = "app.cash.paparazzi:2.0.0-alpha05"
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppDistribution" } firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppDistribution" }
sonarqube = "org.sonarqube:7.3.0.8198" sonarqube = "org.sonarqube:7.3.1.8318"
licensee = "app.cash.licensee:1.14.1" licensee = "app.cash.licensee:1.14.1"
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
gms_google_services = { id = "com.google.gms.google-services", version = "4.4.4" } gms_google_services = { id = "com.google.gms.google-services", version = "4.4.4" }
Binary file not shown.
+2 -2
View File
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
@@ -78,7 +78,7 @@ fun SpaceRoomItemView(
indication = ripple(), indication = ripple(),
interactionSource = remember { MutableInteractionSource() } interactionSource = remember { MutableInteractionSource() }
) )
.onKeyboardContextMenuAction { onLongClick } .onKeyboardContextMenuAction(onLongClick)
Column( Column(
modifier = modifier modifier = modifier
.then(clickModifier) .then(clickModifier)
@@ -258,7 +258,7 @@ class ExoPlayerForPreview(
override fun setPriorityTaskManager(priorityTaskManager: PriorityTaskManager?) {} override fun setPriorityTaskManager(priorityTaskManager: PriorityTaskManager?) {}
override fun isSleepingForOffload(): Boolean = throw NotImplementedError() override fun isSleepingForOffload(): Boolean = throw NotImplementedError()
override fun isTunnelingEnabled(): Boolean = throw NotImplementedError() override fun isTunnelingEnabled(): Boolean = throw NotImplementedError()
override fun isReleased(): Boolean = throw NotImplementedError() override fun isReleased(): Boolean = false
override fun setImageOutput(imageOutput: ImageOutput?) {} override fun setImageOutput(imageOutput: ImageOutput?) {}
override fun setAudioCodecParameters(codecParameters: CodecParameters) {} override fun setAudioCodecParameters(codecParameters: CodecParameters) {}
override fun addAudioCodecParametersChangeListener(listener: CodecParametersChangeListener, keys: List<String>) {} override fun addAudioCodecParametersChangeListener(listener: CodecParametersChangeListener, keys: List<String>) {}
+1
View File
@@ -24,6 +24,7 @@ android {
setupDependencyInjection() setupDependencyInjection()
dependencies { dependencies {
implementation(libs.coroutines.core)
implementation(projects.libraries.androidutils) implementation(projects.libraries.androidutils)
implementation(projects.libraries.core) implementation(projects.libraries.core)
implementation(projects.libraries.di) implementation(projects.libraries.di)
@@ -19,6 +19,10 @@ plugins {
android { android {
namespace = "io.element.android.libraries.pushproviders.firebase" namespace = "io.element.android.libraries.pushproviders.firebase"
buildFeatures {
resValues = true
}
buildTypes { buildTypes {
getByName("release") { getByName("release") {
consumerProguardFiles("consumer-proguard-rules.pro") consumerProguardFiles("consumer-proguard-rules.pro")
@@ -18,6 +18,7 @@ android {
setupDependencyInjection() setupDependencyInjection()
dependencies { dependencies {
implementation(libs.coroutines.core)
implementation(projects.libraries.androidutils) implementation(projects.libraries.androidutils)
implementation(projects.libraries.preferences.api) implementation(projects.libraries.preferences.api)
implementation(projects.libraries.core) implementation(projects.libraries.core)
@@ -9,14 +9,53 @@
package extension package extension
import Versions import Versions
import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.ApplicationDefaultConfig
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.CompileOptions
import com.android.build.api.dsl.LibraryDefaultConfig
import com.android.build.api.dsl.LibraryExtension
import com.android.build.api.dsl.Lint
import isEnterpriseBuild import isEnterpriseBuild
import org.gradle.api.Project import org.gradle.api.Project
import java.io.File import java.io.File
fun CommonExtension<*, *, *, *, *, *>.androidConfig(project: Project) { fun ApplicationExtension.androidAppConfig(project: Project) {
defaultConfig {
compileSdk = Versions.COMPILE_SDK compileSdk = Versions.COMPILE_SDK
defaultConfig(::defaultApplicationConfig)
compileOptions(::defaultCompileOptions)
testOptions(::defaultTestOptions)
lint {
project.defaultLintOptions(this)
}
}
fun LibraryExtension.androidLibraryConfig(project: Project) {
compileSdk = Versions.COMPILE_SDK
defaultConfig(::defaultLibraryConfig)
compileOptions(::defaultCompileOptions)
testOptions(::defaultTestOptions)
lint {
project.defaultLintOptions(this)
}
}
fun ApplicationExtension.composeAppConfig() {
buildFeatures(::defaultComposeBuildFeatures)
packaging(::defaultPackagingOptions)
lint(::defaultComposeLintOptions)
}
fun LibraryExtension.composeLibraryConfig() {
buildFeatures(::defaultComposeBuildFeatures)
packaging(::defaultPackagingOptions)
lint(::defaultComposeLintOptions)
}
fun defaultApplicationConfig(applicationDefaultConfig: ApplicationDefaultConfig) = applicationDefaultConfig.apply {
minSdk = Versions.minSdk minSdk = Versions.minSdk
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -26,16 +65,46 @@ fun CommonExtension<*, *, *, *, *, *>.androidConfig(project: Project) {
} }
} }
compileOptions { fun defaultLibraryConfig(libraryDefaultConfig: LibraryDefaultConfig) = libraryDefaultConfig.apply {
minSdk = Versions.minSdk
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
generatedDensities()
}
}
fun defaultCompileOptions(compileOptions: CompileOptions) = compileOptions.apply {
sourceCompatibility = Versions.javaVersion sourceCompatibility = Versions.javaVersion
targetCompatibility = Versions.javaVersion targetCompatibility = Versions.javaVersion
} }
testOptions { fun defaultTestOptions(testOptions: com.android.build.api.dsl.TestOptions) = testOptions.apply {
unitTests.isReturnDefaultValues = true unitTests.isReturnDefaultValues = true
} }
lint { fun defaultComposeBuildFeatures(buildFeatures: com.android.build.api.dsl.BuildFeatures) = buildFeatures.apply {
compose = true
}
fun defaultPackagingOptions(packagingOptions: com.android.build.api.dsl.Packaging) = packagingOptions.apply {
resources.excludes.apply {
add("META-INF/AL2.0")
add("META-INF/LGPL2.1")
}
}
fun defaultComposeLintOptions(lint: Lint) = lint.apply {
// Extra rules for compose
// Disabled until lint stops inspecting generated ksp files...
// error.add("ComposableLambdaParameterNaming")
error.add("ComposableLambdaParameterPosition")
ignoreTestFixturesSources = true
checkGeneratedSources = false
}
fun Project.defaultLintOptions(lint: Lint) = lint.apply {
lintConfig = File("${project.rootDir}/tools/lint/lint.xml") lintConfig = File("${project.rootDir}/tools/lint/lint.xml")
if (isEnterpriseBuild) { if (isEnterpriseBuild) {
// Disable check on ObsoleteSdkInt for Enterprise builds // Disable check on ObsoleteSdkInt for Enterprise builds
@@ -48,28 +117,3 @@ fun CommonExtension<*, *, *, *, *, *>.androidConfig(project: Project) {
ignoreTestFixturesSources = true ignoreTestFixturesSources = true
checkGeneratedSources = false checkGeneratedSources = false
} }
}
fun CommonExtension<*, *, *, *, *, *>.composeConfig() {
buildFeatures {
compose = true
}
packaging {
resources.excludes.apply {
add("META-INF/AL2.0")
add("META-INF/LGPL2.1")
}
}
lint {
// Extra rules for compose
// Disabled until lint stops inspecting generated ksp files...
// error.add("ComposableLambdaParameterNaming")
error.add("ComposableLambdaParameterPosition")
ignoreTestFixturesSources = true
checkGeneratedSources = false
}
}
@@ -9,9 +9,9 @@
/** /**
* This will generate the plugin "io.element.android-compose-application" to use by app * This will generate the plugin "io.element.android-compose-application" to use by app
*/ */
import extension.androidConfig import extension.androidAppConfig
import extension.commonDependencies import extension.commonDependencies
import extension.composeConfig import extension.composeAppConfig
import extension.composeDependencies import extension.composeDependencies
import extension.setupKover import extension.setupKover
import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.accessors.dm.LibrariesForLibs
@@ -19,14 +19,13 @@ import org.gradle.accessors.dm.LibrariesForLibs
val libs = the<LibrariesForLibs>() val libs = the<LibrariesForLibs>()
plugins { plugins {
id("com.android.application") id("com.android.application")
id("kotlin-android")
id("com.autonomousapps.dependency-analysis") id("com.autonomousapps.dependency-analysis")
id("org.jetbrains.kotlin.plugin.compose") id("org.jetbrains.kotlin.plugin.compose")
} }
android { android {
androidConfig(project) androidAppConfig(project)
composeConfig() composeAppConfig()
compileOptions { compileOptions {
isCoreLibraryDesugaringEnabled = true isCoreLibraryDesugaringEnabled = true
} }
@@ -9,9 +9,9 @@
/** /**
* This will generate the plugin "io.element.android-compose-library", used in android library with compose modules. * This will generate the plugin "io.element.android-compose-library", used in android library with compose modules.
*/ */
import extension.androidConfig import extension.androidLibraryConfig
import extension.commonDependencies import extension.commonDependencies
import extension.composeConfig import extension.composeLibraryConfig
import extension.composeDependencies import extension.composeDependencies
import extension.setupKover import extension.setupKover
import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.accessors.dm.LibrariesForLibs
@@ -19,14 +19,13 @@ import org.gradle.accessors.dm.LibrariesForLibs
val libs = the<LibrariesForLibs>() val libs = the<LibrariesForLibs>()
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android")
id("com.autonomousapps.dependency-analysis") id("com.autonomousapps.dependency-analysis")
id("org.jetbrains.kotlin.plugin.compose") id("org.jetbrains.kotlin.plugin.compose")
} }
android { android {
androidConfig(project) androidLibraryConfig(project)
composeConfig() composeLibraryConfig()
compileOptions { compileOptions {
isCoreLibraryDesugaringEnabled = true isCoreLibraryDesugaringEnabled = true
} }
@@ -9,7 +9,7 @@
/** /**
* This will generate the plugin "io.element.android-library", used in android library without compose modules. * This will generate the plugin "io.element.android-library", used in android library without compose modules.
*/ */
import extension.androidConfig import extension.androidLibraryConfig
import extension.commonDependencies import extension.commonDependencies
import extension.setupKover import extension.setupKover
import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.accessors.dm.LibrariesForLibs
@@ -17,12 +17,11 @@ import org.gradle.accessors.dm.LibrariesForLibs
val libs = the<LibrariesForLibs>() val libs = the<LibrariesForLibs>()
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android")
id("com.autonomousapps.dependency-analysis") id("com.autonomousapps.dependency-analysis")
} }
android { android {
androidConfig(project) androidLibraryConfig(project)
compileOptions { compileOptions {
isCoreLibraryDesugaringEnabled = true isCoreLibraryDesugaringEnabled = true
} }
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package ui
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
/**
* Workaround for Paparazzi 2.0.0-alpha05 / LayoutLib 16.2.1 bug where
* HandlerThread_Delegate calls Thread.setPosixNicenessInternal which doesn't exist on JVM.
* Tracked in https://github.com/cashapp/paparazzi/issues/2342 — fixed in layoutlib 16.2.3.
* Remove this workaround once Paparazzi ships with layoutlib >= 16.2.3.
*
* Paparazzi's PaparazziLogger collects background thread errors and re-throws them via
* assertNoErrors(). This Statement wrapper catches the known NoSuchMethodError so the test
* can pass despite the LayoutLib bug.
*/
class LayoutLibErrorFilterStatement : TestRule {
override fun apply(base: Statement, description: Description): Statement {
return object : Statement() {
@Throws(Throwable::class)
override fun evaluate() {
try {
base.evaluate()
} catch (e: NoSuchMethodError) {
if (e.message?.contains("setPosixNicenessInternal") != true) throw e
} catch (npe: NullPointerException) {
// Also catch this error on `HorizontalFloatingToolbarPreview` and `HorizontalFloatingToolbarNoFabPreview`
if (npe.message?.contains("""Cannot invoke "java.util.ArrayList.size()" because "childrenList" is null""") != true) throw npe
}
}
}
}
}
@@ -29,7 +29,10 @@ class PreviewA11yTest(
@TestParameter(valuesProvider = ComposableA11yPreviewProvider::class) @TestParameter(valuesProvider = ComposableA11yPreviewProvider::class)
val preview: ComposablePreview<AndroidPreviewInfo>, val preview: ComposablePreview<AndroidPreviewInfo>,
) { ) {
@get:Rule @get:Rule(order = 0)
val layoutLibErrorFilterStatement = LayoutLibErrorFilterStatement()
@get:Rule(order = 1)
val paparazziRule = PaparazziPreviewRule.createFor( val paparazziRule = PaparazziPreviewRule.createFor(
preview = preview, preview = preview,
locale = "en", locale = "en",
@@ -28,7 +28,10 @@ class PreviewShard1Test(
@TestParameter(valuesProvider = Shard1ComposablePreviewProvider::class) @TestParameter(valuesProvider = Shard1ComposablePreviewProvider::class)
val preview: ComposablePreview<AndroidPreviewInfo>, val preview: ComposablePreview<AndroidPreviewInfo>,
) { ) {
@get:Rule @get:Rule(order = 0)
val layoutLibErrorFilterStatement = LayoutLibErrorFilterStatement()
@get:Rule(order = 1)
val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en") val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en")
@Test @Test
@@ -28,7 +28,10 @@ class PreviewShard2Test(
@TestParameter(valuesProvider = Shard2ComposablePreviewProvider::class) @TestParameter(valuesProvider = Shard2ComposablePreviewProvider::class)
val preview: ComposablePreview<AndroidPreviewInfo>, val preview: ComposablePreview<AndroidPreviewInfo>,
) { ) {
@get:Rule @get:Rule(order = 0)
val layoutLibErrorFilterStatement = LayoutLibErrorFilterStatement()
@get:Rule(order = 1)
val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en") val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en")
@Test @Test
@@ -28,7 +28,10 @@ class PreviewShard3Test(
@TestParameter(valuesProvider = Shard3ComposablePreviewProvider::class) @TestParameter(valuesProvider = Shard3ComposablePreviewProvider::class)
val preview: ComposablePreview<AndroidPreviewInfo>, val preview: ComposablePreview<AndroidPreviewInfo>,
) { ) {
@get:Rule @get:Rule(order = 0)
val layoutLibErrorFilterStatement = LayoutLibErrorFilterStatement()
@get:Rule(order = 1)
val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en") val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en")
@Test @Test
@@ -28,7 +28,10 @@ class PreviewShard4Test(
@TestParameter(valuesProvider = Shard4ComposablePreviewProvider::class) @TestParameter(valuesProvider = Shard4ComposablePreviewProvider::class)
val preview: ComposablePreview<AndroidPreviewInfo>, val preview: ComposablePreview<AndroidPreviewInfo>,
) { ) {
@get:Rule @get:Rule(order = 0)
val layoutLibErrorFilterStatement = LayoutLibErrorFilterStatement()
@get:Rule(order = 1)
val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en") val paparazziRule = PaparazziPreviewRule.createFor(preview, locale = "en")
@Test @Test

Some files were not shown because too many files have changed in this diff Show More