From 2fd2e51a4249fe4170c0e386cbcee48d7590e01a Mon Sep 17 00:00:00 2001 From: Dustin Byrne Date: Fri, 2 Oct 2026 12:38:10 -0400 Subject: [PATCH 1/2] feat(android): resolve locale against declared app languages --- .changeset/gentle-turtles-nail.md | 5 + buildSrc/src/main/java/PosthogBuildConfig.kt | 3 +- posthog-android/build.gradle.kts | 7 +- posthog-android/consumer-rules.pro | 6 + posthog-android/gradle.lockfile | 134 +++++++------- .../android/internal/LocaleResolution.kt | 27 +++ .../android/internal/PostHogAndroidContext.kt | 5 +- .../android/internal/PostHogLocaleProvider.kt | 159 +++++++++++++++++ .../android/internal/LocaleResolutionTest.kt | 129 ++++++++++++++ .../internal/PostHogLocaleProviderTest.kt | 167 ++++++++++++++++++ 10 files changed, 573 insertions(+), 69 deletions(-) create mode 100644 .changeset/gentle-turtles-nail.md create mode 100644 posthog-android/src/main/java/com/posthog/android/internal/LocaleResolution.kt create mode 100644 posthog-android/src/main/java/com/posthog/android/internal/PostHogLocaleProvider.kt create mode 100644 posthog-android/src/test/java/com/posthog/android/internal/LocaleResolutionTest.kt create mode 100644 posthog-android/src/test/java/com/posthog/android/internal/PostHogLocaleProviderTest.kt diff --git a/.changeset/gentle-turtles-nail.md b/.changeset/gentle-turtles-nail.md new file mode 100644 index 000000000..5b43a0bd1 --- /dev/null +++ b/.changeset/gentle-turtles-nail.md @@ -0,0 +1,5 @@ +--- +"posthog-android": minor +--- + +Resolve `$locale` against the app’s declared supported languages and explicit default when available. Preserve the existing process-locale value when resolution is unavailable. diff --git a/buildSrc/src/main/java/PosthogBuildConfig.kt b/buildSrc/src/main/java/PosthogBuildConfig.kt index 540e69aed..0a584a0a2 100644 --- a/buildSrc/src/main/java/PosthogBuildConfig.kt +++ b/buildSrc/src/main/java/PosthogBuildConfig.kt @@ -66,7 +66,8 @@ object PosthogBuildConfig { val OKHTTP = "4.12.0" val CURTAINS = "1.2.5" - val ANDROIDX_CORE = "1.5.0" + val ANDROIDX_CORE = "1.13.1" + val ANDROIDX_TEST = "1.5.0" val ANDROIDX_COMPOSE = "1.0.0" // matches firebase-bom 34.16.0 diff --git a/posthog-android/build.gradle.kts b/posthog-android/build.gradle.kts index 89dff776b..54d2cc5ac 100644 --- a/posthog-android/build.gradle.kts +++ b/posthog-android/build.gradle.kts @@ -140,9 +140,10 @@ dependencies { testImplementation("org.jetbrains.kotlin:kotlin-test-junit:${PosthogBuildConfig.Kotlin.KOTLIN}") testImplementation("androidx.test:runner:${PosthogBuildConfig.Dependencies.ANDROIDX_RUNNER}") testImplementation("androidx.test.ext:junit:${PosthogBuildConfig.Dependencies.ANDROIDX_JUNIT}") - testImplementation("androidx.test:core:${PosthogBuildConfig.Dependencies.ANDROIDX_CORE}") - testImplementation("androidx.test:core-ktx:${PosthogBuildConfig.Dependencies.ANDROIDX_CORE}") - testImplementation("androidx.test:rules:${PosthogBuildConfig.Dependencies.ANDROIDX_CORE}") + testImplementation("androidx.test:core:${PosthogBuildConfig.Dependencies.ANDROIDX_TEST}") + testImplementation("androidx.test:core-ktx:${PosthogBuildConfig.Dependencies.ANDROIDX_TEST}") + testImplementation("androidx.test:rules:${PosthogBuildConfig.Dependencies.ANDROIDX_TEST}") + testImplementation("androidx.appcompat:appcompat:1.7.0") testImplementation("org.robolectric:robolectric:${PosthogBuildConfig.Dependencies.ROBOLECTRIC}") testImplementation("androidx.activity:activity-compose:1.13.0") testImplementation(platform("androidx.compose:compose-bom:2026.06.01")) diff --git a/posthog-android/consumer-rules.pro b/posthog-android/consumer-rules.pro index 14d6b20f6..ac06e3d35 100644 --- a/posthog-android/consumer-rules.pro +++ b/posthog-android/consumer-rules.pro @@ -124,6 +124,12 @@ -keepnames class com.google.firebase.messaging.FirebaseMessaging ##---------------End: proguard configuration for Firebase Messaging (compileOnly) ---------- +# Optional public AppCompat locale getter used on Android versions before 13. +-if class androidx.appcompat.app.AppCompatDelegate +-keep,allowoptimization class androidx.appcompat.app.AppCompatDelegate { + public static androidx.core.os.LocaleListCompat getApplicationLocales(); +} + # Dead-tap response observation classifies only these known library View implementations. # Preserve names, not members or unused classes; app-defined custom drawing still fails closed. -keepnames class androidx.appcompat.widget.* extends android.view.View diff --git a/posthog-android/gradle.lockfile b/posthog-android/gradle.lockfile index 2e361a4e6..e21fc4954 100644 --- a/posthog-android/gradle.lockfile +++ b/posthog-android/gradle.lockfile @@ -2,78 +2,81 @@ # Manual edits can break the build and are not advised. # This file is expected to be part of source control. # To regenerate this file, run: ./gradlew :posthog-android:dependencies --write-locks -androidx.activity:activity-compose:1.13.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.activity:activity-compose:1.13.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.activity:activity-ktx:1.13.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.activity:activity:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath,testImplementationDependenciesMetadata -androidx.activity:activity:1.13.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.annotation:annotation-experimental:1.1.0=testImplementationDependenciesMetadata -androidx.annotation:annotation-experimental:1.4.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.activity:activity:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath +androidx.activity:activity:1.13.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.annotation:annotation-experimental:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath +androidx.annotation:annotation-experimental:1.4.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.annotation:annotation-jvm:1.6.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath androidx.annotation:annotation-jvm:1.9.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.annotation:annotation:1.2.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.annotation:annotation:1.3.0=compileOnlyDependenciesMetadata -androidx.annotation:annotation:1.7.0-beta01=testImplementationDependenciesMetadata -androidx.annotation:annotation:1.9.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.arch.core:core-common:2.1.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata -androidx.arch.core:core-common:2.2.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.arch.core:core-runtime:2.0.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata -androidx.arch.core:core-runtime:2.2.0=debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.annotation:annotation:1.6.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath +androidx.annotation:annotation:1.9.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.appcompat:appcompat-resources:1.7.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.appcompat:appcompat:1.7.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.arch.core:core-common:2.1.0=compileOnlyDependenciesMetadata +androidx.arch.core:core-common:2.2.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.arch.core:core-runtime:2.0.0=compileOnlyDependenciesMetadata +androidx.arch.core:core-runtime:2.2.0=debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.autofill:autofill:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.collection:collection-jvm:1.5.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.collection:collection-ktx:1.5.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.collection:collection:1.0.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath -androidx.collection:collection:1.1.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata -androidx.collection:collection:1.5.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.collection:collection:1.1.0=compileOnlyDependenciesMetadata +androidx.collection:collection:1.5.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.animation:animation-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.animation:animation-core-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.animation:animation-core:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.animation:animation:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.animation:animation-core:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.compose.animation:animation:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.foundation:foundation-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.foundation:foundation-layout-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.foundation:foundation-layout:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.foundation:foundation:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.foundation:foundation-layout:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.compose.foundation:foundation:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.material3:material3-android:1.4.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.material3:material3:1.4.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.material3:material3:1.4.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.material:material-ripple-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.material:material-ripple:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.material:material-ripple:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.runtime:runtime-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.runtime:runtime-annotation-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.runtime:runtime-annotation:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.runtime:runtime-annotation:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.runtime:runtime-retain-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.runtime:runtime-retain:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.runtime:runtime-retain:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.runtime:runtime-saveable-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.runtime:runtime-saveable:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath -androidx.compose.runtime:runtime-saveable:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.runtime:runtime-saveable:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.runtime:runtime:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath -androidx.compose.runtime:runtime:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.runtime:runtime:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.ui:ui-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.ui:ui-geometry-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.ui:ui-geometry:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath -androidx.compose.ui:ui-geometry:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-geometry:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.ui:ui-graphics-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.ui:ui-graphics:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath -androidx.compose.ui:ui-graphics:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-graphics:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.ui:ui-test-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.ui:ui-test-junit4-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.ui:ui-test-junit4:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.ui:ui-test:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-test-junit4:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.compose.ui:ui-test:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.ui:ui-text-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.ui:ui-text:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath -androidx.compose.ui:ui-text:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-text:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.ui:ui-unit-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.compose.ui:ui-unit:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath -androidx.compose.ui:ui-unit:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-unit:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.ui:ui-util-android:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose.ui:ui-util:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-util:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.compose.ui:ui:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath -androidx.compose.ui:ui:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.compose:compose-bom:2026.06.01=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui:1.11.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.compose:compose-bom:2026.06.01=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.concurrent:concurrent-futures-ktx:1.1.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.concurrent:concurrent-futures:1.1.0=debugAndroidTestRuntimeClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata -androidx.core:core-ktx:1.18.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.core:core-viewtree:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.core:core:1.18.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.core:core:1.2.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata -androidx.core:core:1.5.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath +androidx.core:core-ktx:1.18.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.core:core-viewtree:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.core:core:1.13.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath +androidx.core:core:1.18.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.core:core:1.2.0=compileOnlyDependenciesMetadata +androidx.cursoradapter:cursoradapter:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.customview:customview-poolingcontainer:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.customview:customview:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.datastore:datastore-android:1.1.7=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath @@ -89,58 +92,61 @@ androidx.datastore:datastore-preferences-proto:1.1.7=debugUnitTestRuntimeClasspa androidx.datastore:datastore-preferences:1.1.7=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.datastore:datastore:1.1.7=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.documentfile:documentfile:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.drawerlayout:drawerlayout:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.dynamicanimation:dynamicanimation:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.emoji2:emoji2-views-helper:1.4.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.emoji2:emoji2:1.4.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.fragment:fragment:1.1.0=compileOnlyDependenciesMetadata,debugCompileClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.fragment:fragment:1.1.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath +androidx.fragment:fragment:1.5.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.graphics:graphics-path:1.0.1=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.interpolator:interpolator:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.interpolator:interpolator:1.0.0=debugAndroidTestRuntimeClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.legacy:legacy-support-core-utils:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-common-java8:2.6.2=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-common-java8:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-common-jvm:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-common:2.1.0=compileOnlyDependenciesMetadata -androidx.lifecycle:lifecycle-common:2.3.1=testImplementationDependenciesMetadata androidx.lifecycle:lifecycle-common:2.6.2=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath -androidx.lifecycle:lifecycle-common:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-livedata-core-ktx:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-livedata-core:2.0.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-common:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-livedata-core-ktx:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-livedata-core:2.0.0=compileOnlyDependenciesMetadata androidx.lifecycle:lifecycle-livedata-core:2.6.2=debugCompileClasspath,releaseCompileClasspath -androidx.lifecycle:lifecycle-livedata-core:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-livedata:2.0.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-livedata-core:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-livedata:2.0.0=compileOnlyDependenciesMetadata androidx.lifecycle:lifecycle-livedata:2.6.2=debugCompileClasspath,releaseCompileClasspath -androidx.lifecycle:lifecycle-livedata:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-livedata:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.lifecycle:lifecycle-process:2.6.2=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-process:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-runtime-android:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-runtime-compose-android:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-runtime-compose:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-runtime-compose:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.lifecycle:lifecycle-runtime-ktx-android:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-runtime-ktx:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-runtime:2.1.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-runtime:2.1.0=compileOnlyDependenciesMetadata androidx.lifecycle:lifecycle-runtime:2.6.2=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath -androidx.lifecycle:lifecycle-runtime:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-runtime:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.lifecycle:lifecycle-viewmodel-android:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.4=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-viewmodel-savedstate-android:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-viewmodel-savedstate:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.lifecycle:lifecycle-viewmodel:2.1.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-viewmodel-savedstate:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.lifecycle:lifecycle-viewmodel:2.1.0=compileOnlyDependenciesMetadata androidx.lifecycle:lifecycle-viewmodel:2.6.2=debugCompileClasspath,releaseCompileClasspath -androidx.lifecycle:lifecycle-viewmodel:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.loader:loader:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.localbroadcastmanager:localbroadcastmanager:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.navigationevent:navigationevent-android:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.navigationevent:navigationevent-compose-android:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.navigationevent:navigationevent-compose:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.navigationevent:navigationevent:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.navigationevent:navigationevent-compose:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.navigationevent:navigationevent:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.print:print:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.profileinstaller:profileinstaller:1.3.0=debugAndroidTestRuntimeClasspath,debugRuntimeClasspath,releaseRuntimeClasspath androidx.profileinstaller:profileinstaller:1.4.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.resourceinspection:resourceinspection-annotation:1.0.1=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.savedstate:savedstate-android:1.3.2=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.savedstate:savedstate-compose-android:1.3.2=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.savedstate:savedstate-compose:1.3.2=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.savedstate:savedstate-compose:1.3.2=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.savedstate:savedstate-ktx:1.3.2=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.savedstate:savedstate:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath,testImplementationDependenciesMetadata -androidx.savedstate:savedstate:1.3.2=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.savedstate:savedstate:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath +androidx.savedstate:savedstate:1.3.2=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.startup:startup-runtime:1.1.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.test.espresso:espresso-core:3.5.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.test.espresso:espresso-idling-resource:3.6.1=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath @@ -156,8 +162,10 @@ androidx.tracing:tracing:1.0.0=debugAndroidTestRuntimeClasspath,debugRuntimeClas androidx.tracing:tracing:1.1.0=testImplementationDependenciesMetadata androidx.tracing:tracing:1.2.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.transition:transition:1.6.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.versionedparcelable:versionedparcelable:1.1.0=compileOnlyDependenciesMetadata,testImplementationDependenciesMetadata -androidx.versionedparcelable:versionedparcelable:1.1.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.vectordrawable:vectordrawable-animated:1.1.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.vectordrawable:vectordrawable:1.1.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.versionedparcelable:versionedparcelable:1.1.0=compileOnlyDependenciesMetadata +androidx.versionedparcelable:versionedparcelable:1.1.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.viewpager:viewpager:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.window:window-core-android:1.5.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.window:window-core:1.5.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath @@ -370,18 +378,18 @@ org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3=_internal-unified-test-platf org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0=compileOnlyDependenciesMetadata,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.9.0=compileOnlyDependenciesMetadata,debugCompileClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm:1.9.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.jetbrains.kotlinx:kotlinx-html-jvm:0.9.1=dokkaGfmPartialPlugin,dokkaGfmPlugin,dokkaHtmlPartialPlugin,dokkaHtmlPlugin,dokkaJavadocPartialPlugin,dokkaJavadocPlugin,dokkaJekyllPartialPlugin,dokkaJekyllPlugin org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.jetbrains.kotlinx:kover-jvm-agent:0.9.9=koverJvmAgent,koverJvmReporter org.jetbrains:annotations:13.0=bcv-rt-jvm-cp-resolver,debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,releaseCompileClasspath,releaseRuntimeClasspath org.jetbrains:annotations:23.0.0=_internal-unified-test-platform-android-device-provider-ddmlib,_internal-unified-test-platform-android-device-provider-gradle,_internal-unified-test-platform-android-driver-instrumentation,_internal-unified-test-platform-android-test-plugin,_internal-unified-test-platform-android-test-plugin-host-additional-test-output,_internal-unified-test-platform-android-test-plugin-host-apk-installer,_internal-unified-test-platform-android-test-plugin-host-coverage,_internal-unified-test-platform-android-test-plugin-host-device-info,_internal-unified-test-platform-android-test-plugin-host-emulator-control,_internal-unified-test-platform-android-test-plugin-host-logcat,_internal-unified-test-platform-android-test-plugin-host-retention,_internal-unified-test-platform-android-test-plugin-result-listener-gradle,_internal-unified-test-platform-core,_internal-unified-test-platform-launcher,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,dokkaGfmPartialPlugin,dokkaGfmPartialRuntime,dokkaGfmPlugin,dokkaGfmRuntime,dokkaHtmlPartialPlugin,dokkaHtmlPartialRuntime,dokkaHtmlPlugin,dokkaHtmlRuntime,dokkaJavadocPartialPlugin,dokkaJavadocPartialRuntime,dokkaJavadocPlugin,dokkaJavadocRuntime,dokkaJekyllPartialPlugin,dokkaJekyllPartialRuntime,dokkaJekyllPlugin,dokkaJekyllRuntime,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.jetbrains:markdown-jvm:0.5.2=dokkaGfmPartialPlugin,dokkaGfmPlugin,dokkaHtmlPartialPlugin,dokkaHtmlPlugin,dokkaJavadocPartialPlugin,dokkaJavadocPlugin,dokkaJekyllPartialPlugin,dokkaJekyllPlugin org.jetbrains:markdown:0.5.2=dokkaGfmPartialPlugin,dokkaGfmPlugin,dokkaHtmlPartialPlugin,dokkaHtmlPlugin,dokkaJavadocPartialPlugin,dokkaJavadocPlugin,dokkaJekyllPartialPlugin,dokkaJekyllPlugin org.jsoup:jsoup:1.16.1=dokkaGfmPartialPlugin,dokkaGfmPlugin,dokkaHtmlPartialPlugin,dokkaHtmlPlugin,dokkaJavadocPartialPlugin,dokkaJavadocPlugin,dokkaJekyllPartialPlugin,dokkaJekyllPlugin -org.jspecify:jspecify:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jspecify:jspecify:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.mockito.kotlin:mockito-kotlin:4.1.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.mockito:mockito-core:4.11.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata org.mockito:mockito-inline:4.11.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata diff --git a/posthog-android/src/main/java/com/posthog/android/internal/LocaleResolution.kt b/posthog-android/src/main/java/com/posthog/android/internal/LocaleResolution.kt new file mode 100644 index 000000000..1bc56cb6d --- /dev/null +++ b/posthog-android/src/main/java/com/posthog/android/internal/LocaleResolution.kt @@ -0,0 +1,27 @@ +package com.posthog.android.internal + +import androidx.core.os.LocaleListCompat +import java.util.Locale + +internal data class SupportedLocales( + val locales: List, + val defaultLocale: Locale? = null, +) + +/** Negotiates declared language support, not the language of every displayed resource. */ +internal fun resolveLocale( + preferences: List, + supported: SupportedLocales, +): Locale? { + for (preferred in preferences) { + val match = + supported.locales.firstOrNull { it == preferred } + ?: supported.locales.firstOrNull { + LocaleListCompat.matchesLanguageAndScript(it, preferred) + } + if (match != null) return match + } + return supported.defaultLocale?.takeIf { it in supported.locales } +} + +internal fun LocaleListCompat.toLocales(): List = (0 until size()).mapNotNull { this[it] } diff --git a/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt b/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt index 26432dff6..7439bac78 100644 --- a/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt +++ b/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt @@ -5,7 +5,6 @@ import android.content.pm.PackageInfo import android.os.Build import com.posthog.android.PostHogAndroidConfig import com.posthog.internal.PostHogContext -import java.util.Locale import java.util.TimeZone /** @@ -20,6 +19,8 @@ internal class PostHogAndroidContext( private val packageInfoProvider: () -> PackageInfo? = { getPackageInfo(context, config) }, private val networkPropertiesProvider: () -> Map, ) : PostHogContext { + private val localeProvider = PostHogLocaleProvider(context, config) + private val cacheSdkInfo by lazy { val sdkInfo = mutableMapOf() @@ -67,7 +68,7 @@ internal class PostHogAndroidContext( override fun getDynamicContext(): Map { val dynamicContext = mutableMapOf() - dynamicContext["\$locale"] = "${Locale.getDefault().language}-${Locale.getDefault().country}" + dynamicContext["\$locale"] = localeProvider.getLocale() System.getProperty("http.agent")?.let { dynamicContext["\$user_agent"] = it // Mirrored into $raw_user_agent, the standardized property PostHog's diff --git a/posthog-android/src/main/java/com/posthog/android/internal/PostHogLocaleProvider.kt b/posthog-android/src/main/java/com/posthog/android/internal/PostHogLocaleProvider.kt new file mode 100644 index 000000000..eb0440ca4 --- /dev/null +++ b/posthog-android/src/main/java/com/posthog/android/internal/PostHogLocaleProvider.kt @@ -0,0 +1,159 @@ +package com.posthog.android.internal + +import android.app.LocaleConfig +import android.app.LocaleManager +import android.content.Context +import android.content.res.Resources +import android.os.Build +import android.util.AttributeSet +import androidx.annotation.RequiresApi +import androidx.core.os.ConfigurationCompat +import androidx.core.os.LocaleListCompat +import com.posthog.android.PostHogAndroidConfig +import org.xmlpull.v1.XmlPullParser +import java.util.Locale + +/** Reads packaged declarations once, but refreshes preferences and runtime overrides per event. */ +internal class PostHogLocaleProvider( + private val context: Context, + private val config: PostHogAndroidConfig, +) { + private val manifestSupport by lazy { + try { + readManifestLocaleConfig(context) + } catch (e: Throwable) { + config.logger.log("Unable to read the app locale declaration: $e.") + null + } + } + private val platformSupport by lazy { + if (Build.VERSION.SDK_INT >= 33) readPlatformSupport() else null + } + private val appCompatLocales = OptionalAppCompatLocales() + + fun getLocale(): String { + try { + val supported = if (Build.VERSION.SDK_INT >= 33) currentPlatformSupport() else manifestSupport + if (supported != null) { + resolveLocale(requestedLocales(), supported)?.let { return it.toLanguageTag() } + } + } catch (e: Throwable) { + config.logger.log("Unable to resolve the app locale: $e.") + } + val locale = Locale.getDefault() + return "${locale.language}-${locale.country}" + } + + private fun requestedLocales(): List { + if (Build.VERSION.SDK_INT >= 33) { + val manager = context.getSystemService(LocaleManager::class.java) + val app = manager.applicationLocales + val locales = if (!app.isEmpty) app else manager.systemLocales + return (0 until locales.size()).map { locales[it] } + } + return appCompatLocales.getLocales().ifEmpty { + ConfigurationCompat.getLocales(Resources.getSystem().configuration).toLocales() + } + } + + @RequiresApi(33) + private fun readPlatformSupport(): SupportedLocales? { + val localeConfig = + if (Build.VERSION.SDK_INT >= 34) { + LocaleConfig.fromContextIgnoringOverride(context) + } else { + LocaleConfig(context) + } + if (localeConfig.status != LocaleConfig.STATUS_SUCCESS) return null + val locales = localeConfig.supportedLocales ?: return null + val supported = (0 until locales.size()).map { locales[it] } + val declared = manifestSupport + val defaultLocale = declared?.takeIf { it.locales.toSet() == supported.toSet() }?.defaultLocale + return SupportedLocales(supported, defaultLocale) + } + + @RequiresApi(33) + private fun currentPlatformSupport(): SupportedLocales? { + if (Build.VERSION.SDK_INT >= 34) { + val override = context.getSystemService(LocaleManager::class.java).overrideLocaleConfig + if (override != null) { + // A runtime override must not inherit the packaged declaration's default. + val locales = override.supportedLocales ?: return null + val defaultLocale = if (Build.VERSION.SDK_INT >= 35) override.defaultLocale else null + return SupportedLocales((0 until locales.size()).map { locales[it] }, defaultLocale) + } + } + return platformSupport + } +} + +/** Access AppCompat's public getter without making AppCompat a runtime dependency. */ +internal class OptionalAppCompatLocales( + private val className: String = "androidx.appcompat.app.AppCompatDelegate", +) { + private val getter by lazy { + try { + Class.forName(className, false, javaClass.classLoader).getMethod("getApplicationLocales") + } catch (_: ReflectiveOperationException) { + null + } catch (_: LinkageError) { + null + } + } + + fun getLocales(): List { + return try { + (getter?.invoke(null) as? LocaleListCompat)?.toLocales().orEmpty() + } catch (_: Exception) { + emptyList() + } catch (_: LinkageError) { + emptyList() + } + } +} + +private const val ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android" + +internal fun readManifestLocaleConfig(context: Context): SupportedLocales? { + val resourceId = + context.assets.openXmlResourceParser("AndroidManifest.xml").use { parser -> + var id = 0 + while (parser.eventType != XmlPullParser.END_DOCUMENT) { + if (parser.eventType == XmlPullParser.START_TAG && parser.name == "application") { + id = parser.getAttributeResourceValue(ANDROID_NAMESPACE, "localeConfig", 0) + break + } + parser.next() + } + id + } + if (resourceId == 0) return null + return context.resources.getXml(resourceId).use { parseLocaleConfig(it, context::getString) } +} + +internal fun parseLocaleConfig( + parser: XmlPullParser, + resolveString: (Int) -> String, +): SupportedLocales? { + fun attribute(name: String): String? { + val reference = (parser as? AttributeSet)?.getAttributeResourceValue(ANDROID_NAMESPACE, name, 0) ?: 0 + return if (reference != 0) resolveString(reference) else parser.getAttributeValue(ANDROID_NAMESPACE, name) + } + + while (parser.eventType != XmlPullParser.START_TAG && parser.eventType != XmlPullParser.END_DOCUMENT) parser.next() + if (parser.eventType != XmlPullParser.START_TAG || parser.name != "locale-config") return null + val rootDepth = parser.depth + val defaultLocale = attribute("defaultLocale")?.let { Locale.Builder().setLanguageTag(it).build() } + val locales = mutableListOf() + while (parser.next() != XmlPullParser.END_DOCUMENT) { + if (parser.eventType == XmlPullParser.END_TAG && parser.depth == rootDepth) break + if (parser.eventType == XmlPullParser.START_TAG && parser.depth == rootDepth + 1 && parser.name == "locale") { + val tag = attribute("name") ?: return null + val locale = Locale.Builder().setLanguageTag(tag).build() + if (locale.language.isEmpty()) return null + locales.add(locale) + } + } + if (defaultLocale != null && defaultLocale !in locales) return null + return SupportedLocales(locales.distinct(), defaultLocale) +} diff --git a/posthog-android/src/test/java/com/posthog/android/internal/LocaleResolutionTest.kt b/posthog-android/src/test/java/com/posthog/android/internal/LocaleResolutionTest.kt new file mode 100644 index 000000000..b99f1670b --- /dev/null +++ b/posthog-android/src/test/java/com/posthog/android/internal/LocaleResolutionTest.kt @@ -0,0 +1,129 @@ +package com.posthog.android.internal + +import android.util.Xml +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import java.util.Locale +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [24, 32, 33, 35]) +internal class LocaleResolutionTest { + private fun locales(vararg tags: String) = tags.map(Locale::forLanguageTag) + + @Test + fun `respects preference order and matches regional languages`() { + val supported = SupportedLocales(locales("en", "de")) + assertEquals(Locale.GERMAN, resolveLocale(locales("ru-RU", "de-CH", "en-US"), supported)) + } + + @Test + fun `prefers exact support before broad regional matching`() { + val supported = SupportedLocales(locales("en-US", "en-GB")) + assertEquals(Locale.UK, resolveLocale(locales("en-GB"), supported)) + } + + @Test + fun `preserves script distinctions`() { + val supported = SupportedLocales(locales("zh-Hans", "zh-Hant")) + assertEquals("zh-Hant", resolveLocale(locales("zh-TW"), supported)?.toLanguageTag()) + assertEquals("zh-Hans", resolveLocale(locales("zh-CN"), supported)?.toLanguageTag()) + assertNull(resolveLocale(locales("sr-Latn"), SupportedLocales(locales("sr-Cyrl")))) + } + + @Test + fun `pseudo locales require an exact match`() { + assertNull(resolveLocale(locales("en-XA"), SupportedLocales(locales("en")))) + assertEquals("en-XA", resolveLocale(locales("en-XA"), SupportedLocales(locales("en", "en-XA")))?.toLanguageTag()) + } + + @Test + fun `uses declared fallback only when supported`() { + assertEquals(Locale.ENGLISH, resolveLocale(locales("de-CH"), SupportedLocales(locales("en"), Locale.ENGLISH))) + assertNull(resolveLocale(locales("de-CH"), SupportedLocales(locales("en")))) + assertNull(resolveLocale(locales("ru"), SupportedLocales(locales("de"), Locale.ENGLISH))) + assertNull(resolveLocale(locales("de"), SupportedLocales(emptyList()))) + } + + @Test + @Config(sdk = [23]) + fun `matches basic language preferences on Android 6`() { + assertEquals(Locale.GERMAN, resolveLocale(locales("de-CH"), SupportedLocales(locales("en", "de")))) + assertEquals(Locale.ENGLISH, resolveLocale(locales("ru"), SupportedLocales(locales("en"), Locale.ENGLISH))) + } + + private fun parse(xml: String): SupportedLocales? { + val parser = Xml.newPullParser().apply { setInput(xml.reader()) } + return parseLocaleConfig(parser) { error("Unexpected resource reference $it") } + } + + @Test + fun `parses declared locales and explicit default`() { + val supported = + parse( + """ + + + + + """.trimIndent(), + ) + assertEquals(SupportedLocales(locales("en", "de"), Locale.ENGLISH), supported) + } + + @Test + fun `does not infer default from declaration order`() { + val supported = + parse( + """ + + + + + """.trimIndent(), + ) + assertEquals(SupportedLocales(locales("de", "en")), supported) + } + + @Test + fun `rejects invalid root and default`() { + assertNull( + parse( + """ + + + + """.trimIndent(), + ), + ) + assertNull( + parse( + """ + + + + """.trimIndent(), + ), + ) + } + + @Test + fun `ignores locales nested inside unknown elements`() { + assertEquals( + SupportedLocales(locales("en")), + parse( + """ + + + + + + + """.trimIndent(), + ), + ) + } +} diff --git a/posthog-android/src/test/java/com/posthog/android/internal/PostHogLocaleProviderTest.kt b/posthog-android/src/test/java/com/posthog/android/internal/PostHogLocaleProviderTest.kt new file mode 100644 index 000000000..127f73120 --- /dev/null +++ b/posthog-android/src/test/java/com/posthog/android/internal/PostHogLocaleProviderTest.kt @@ -0,0 +1,167 @@ +package com.posthog.android.internal + +import android.app.LocaleConfig +import android.app.LocaleManager +import android.content.Context +import android.content.res.AssetManager +import android.content.res.Resources +import android.content.res.XmlResourceParser +import android.os.LocaleList +import android.util.Xml +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.os.LocaleListCompat +import androidx.test.core.app.ApplicationProvider +import com.posthog.android.PostHogAndroidConfig +import org.junit.runner.RunWith +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import java.util.Locale +import kotlin.test.AfterTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [23, 32]) +internal class PostHogLocaleProviderTest { + private val initialLocale = Locale.getDefault() + private val initialAppLocales = AppCompatDelegate.getApplicationLocales() + private val config = PostHogAndroidConfig("test") + + @AfterTest + fun restoreLocales() { + Locale.setDefault(initialLocale) + AppCompatDelegate.setApplicationLocales(initialAppLocales) + } + + @Test + fun `dynamic event context uses declared app support`() { + val context = declaredContext() + val properties = PostHogAndroidContext(context, config, networkPropertiesProvider = { emptyMap() }) + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("ru-RU,de-CH,en-US")) + assertEquals("de", properties.getDynamicContext()["\$locale"]) + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("en-US")) + assertEquals("en", properties.getDynamicContext()["\$locale"]) + } + + @Test + fun `falls back to declared default when preferences do not match`() { + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("ru-RU")) + assertEquals("en", PostHogLocaleProvider(declaredContext(), config).getLocale()) + } + + @Test + fun `unmatched preferences without declared default retain existing value`() { + val xml = + """ + + + + """.trimIndent() + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("ru-RU")) + Locale.setDefault(Locale.forLanguageTag("de-CH")) + assertEquals("de-CH", PostHogLocaleProvider(declaredContext(xml), config).getLocale()) + } + + @Test + @Config(sdk = [23, 32, 33, 35]) + fun `missing declaration retains existing value including missing country`() { + val context = ApplicationProvider.getApplicationContext() + val provider = PostHogLocaleProvider(context, config) + Locale.setDefault(Locale.forLanguageTag("de-CH")) + assertEquals("de-CH", provider.getLocale()) + Locale.setDefault(Locale.ENGLISH) + assertEquals("en-", provider.getLocale()) + } + + @Test + fun `malformed declaration cannot prevent event context collection`() { + Locale.setDefault(Locale.US) + val context = declaredContext("") + assertEquals("en-US", PostHogLocaleProvider(context, config).getLocale()) + } + + @Test + fun `absent or older AppCompat is optional`() { + assertTrue(OptionalAppCompatLocales("missing.AppCompatDelegate").getLocales().isEmpty()) + assertTrue(OptionalAppCompatLocales("java.lang.String").getLocales().isEmpty()) + } + + @Test + fun `optional getter reads preference changes`() { + val source = OptionalAppCompatLocales() + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("de-CH,en-US")) + assertEquals(listOf("de-CH", "en-US"), source.getLocales().map { it.toLanguageTag() }) + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("en")) + assertEquals(listOf("en"), source.getLocales().map { it.toLanguageTag() }) + } + + @Test + @Config(sdk = [34, 35]) + fun `native preferences and runtime supported locales are refreshed`() { + // Robolectric's LocaleManager shadow does not implement runtime locale-config overrides. + val context = mock() + val manager = mock() + whenever(context.getSystemService(LocaleManager::class.java)).thenReturn(manager) + whenever(manager.applicationLocales).thenReturn(LocaleList.forLanguageTags("de-CH,en-US")) + whenever(manager.overrideLocaleConfig).thenReturn(LocaleConfig(LocaleList.forLanguageTags("en,de"))) + val provider = PostHogLocaleProvider(context, config) + assertEquals("de", provider.getLocale()) + whenever(manager.overrideLocaleConfig).thenReturn(LocaleConfig(LocaleList.forLanguageTags("en"))) + assertEquals("en", provider.getLocale()) + whenever(manager.overrideLocaleConfig).thenReturn(null) + Locale.setDefault(Locale.FRANCE) + assertEquals("fr-FR", provider.getLocale()) + } + + private fun declaredContext( + xml: String = + """ + + + + + """.trimIndent(), + ): Context { + val context = mock() + val assets = mock() + val resources = mock() + whenever(context.assets).thenReturn(assets) + whenever(context.resources).thenReturn(resources) + whenever(assets.openXmlResourceParser("AndroidManifest.xml")).thenAnswer { + parser( + """ + + + + """.trimIndent(), + 123, + ) + } + whenever(resources.getXml(123)).thenAnswer { parser(xml) } + return context + } + + private fun parser( + xml: String, + manifestReference: Int = 0, + ): XmlResourceParser { + val source = Xml.newPullParser().apply { setInput(xml.reader()) } + val parser = mock() + whenever(parser.eventType).thenAnswer { source.eventType } + whenever(parser.name).thenAnswer { source.name } + whenever(parser.depth).thenAnswer { source.depth } + whenever(parser.next()).thenAnswer { source.next() } + for (name in listOf("localeConfig", "defaultLocale", "name")) { + whenever( + parser.getAttributeResourceValue("http://schemas.android.com/apk/res/android", name, 0), + ).thenReturn(if (name == "localeConfig") manifestReference else 0) + whenever(parser.getAttributeValue("http://schemas.android.com/apk/res/android", name)).thenAnswer { + source.getAttributeValue("http://schemas.android.com/apk/res/android", name) + } + } + return parser + } +} From 7c5e191f37a2d3346e6202a5addb08e46c262919 Mon Sep 17 00:00:00 2001 From: Dustin Byrne Date: Fri, 2 Oct 2026 12:47:52 -0400 Subject: [PATCH 2/2] fix(android): preserve compile SDK 33 consumer compatibility --- buildSrc/src/main/java/PosthogBuildConfig.kt | 2 +- posthog-android/gradle.lockfile | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/buildSrc/src/main/java/PosthogBuildConfig.kt b/buildSrc/src/main/java/PosthogBuildConfig.kt index 0a584a0a2..c4897423d 100644 --- a/buildSrc/src/main/java/PosthogBuildConfig.kt +++ b/buildSrc/src/main/java/PosthogBuildConfig.kt @@ -66,7 +66,7 @@ object PosthogBuildConfig { val OKHTTP = "4.12.0" val CURTAINS = "1.2.5" - val ANDROIDX_CORE = "1.13.1" + val ANDROIDX_CORE = "1.9.0" val ANDROIDX_TEST = "1.5.0" val ANDROIDX_COMPOSE = "1.0.0" diff --git a/posthog-android/gradle.lockfile b/posthog-android/gradle.lockfile index e21fc4954..37de66ac4 100644 --- a/posthog-android/gradle.lockfile +++ b/posthog-android/gradle.lockfile @@ -6,12 +6,11 @@ androidx.activity:activity-compose:1.13.0=debugUnitTestCompileClasspath,debugUni androidx.activity:activity-ktx:1.13.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.activity:activity:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath androidx.activity:activity:1.13.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata -androidx.annotation:annotation-experimental:1.4.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath +androidx.annotation:annotation-experimental:1.3.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.annotation:annotation-experimental:1.4.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata -androidx.annotation:annotation-jvm:1.6.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath androidx.annotation:annotation-jvm:1.9.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.annotation:annotation:1.2.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.annotation:annotation:1.3.0=compileOnlyDependenciesMetadata -androidx.annotation:annotation:1.6.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.annotation:annotation:1.9.1=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.appcompat:appcompat-resources:1.7.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.appcompat:appcompat:1.7.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata @@ -73,9 +72,9 @@ androidx.concurrent:concurrent-futures-ktx:1.1.0=debugUnitTestCompileClasspath,d androidx.concurrent:concurrent-futures:1.1.0=debugAndroidTestRuntimeClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.core:core-ktx:1.18.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.core:core-viewtree:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata -androidx.core:core:1.13.1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.core:core:1.18.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.core:core:1.2.0=compileOnlyDependenciesMetadata +androidx.core:core:1.9.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.cursoradapter:cursoradapter:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.customview:customview-poolingcontainer:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.customview:customview:1.0.0=compileOnlyDependenciesMetadata,debugCompileClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata @@ -99,7 +98,7 @@ androidx.emoji2:emoji2:1.4.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntim androidx.fragment:fragment:1.1.0=compileOnlyDependenciesMetadata,debugCompileClasspath,releaseCompileClasspath androidx.fragment:fragment:1.5.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.graphics:graphics-path:1.0.1=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath -androidx.interpolator:interpolator:1.0.0=debugAndroidTestRuntimeClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata +androidx.interpolator:interpolator:1.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath,testImplementationDependenciesMetadata androidx.legacy:legacy-support-core-utils:1.0.0=debugUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath androidx.lifecycle:lifecycle-common-java8:2.6.2=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,implementationDependenciesMetadata,releaseCompileClasspath,releaseRuntimeClasspath androidx.lifecycle:lifecycle-common-java8:2.9.4=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath