[DO NOT MERGE] 11.0 dev branch - #4125
AlvaroBrey wants to merge 10 commits into
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 351c2b5. Configure here.
📸 Snapshot Test54 modified, 578 unchanged
🛸 Powered by Emerge Tools |
Public API changes in ui:debugview (2 removed)- public final class InternalDebugRevenueCatScreenViewModelFactory extends androidx.lifecycle.ViewModelProvider.NewInstanceFactory
- ctor public InternalDebugRevenueCatScreenViewModelFactory(kotlin.jvm.functions.Function1<? super com.revenuecat.purchases.models.StoreTransaction,kotlin.Unit> onPurchaseCompleted, kotlin.jvm.functi…Generated by 🚫 Danger |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4125 +/- ##
==========================================
+ Coverage 83.69% 83.72% +0.03%
==========================================
Files 461 461
Lines 18831 18826 -5
Branches 2854 2853 -1
==========================================
+ Hits 15760 15763 +3
+ Misses 2155 2146 -9
- Partials 916 917 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
e6d3d49 to
10f2532
Compare
2 builds increased size
TestPurchasesUIAndroidCompatibility 1.0 (1)
|
| Item | Install Size Change | Download Size Change |
|---|---|---|
| 🗑 androidx.compose.material.icons | ⬇️ -378.3 kB | ⬇️ -126.2 kB |
| 🗑 androidx.compose.runtime.changelist | ⬇️ -66.1 kB | ⬇️ -22.1 kB |
| 📝 androidx.compose.runtime.LinkComposer | ⬆️ 60.8 kB | ⬆️ 20.6 kB |
| 📝 androidx.compose.runtime.GapComposer | ⬆️ 49.0 kB | ⬆️ 16.6 kB |
| 📝 androidx.compose.material3.SearchBarKt | ⬆️ 46.3 kB | ⬆️ 15.7 kB |
SDKSizeTesting 1.0 (1)
com.revenuecat.testapps.sdksizetesting
⚖️ Compare build
⏱️ Analyze build performance
Total install size change: ⬆️ 2.9 MB (7.9%)
Total download size change: ⬆️ 1.1 MB (8.82%)
Largest size changes
| Item | Install Size Change | Download Size Change |
|---|---|---|
| 🗑 androidx.compose.material.icons | ⬇️ -226.4 kB | ⬇️ -76.8 kB |
| 🗑 androidx.compose.runtime.changelist | ⬇️ -37.8 kB | ⬇️ -12.8 kB |
| resources.arsc | ⬆️ 51.4 kB | ⬆️ 12.5 kB |
| com.google.android.gms.internal.play_billing.zzhe | ⬇️ -28.0 kB | ⬇️ -10.5 kB |
| com.google.android.gms.internal.play_billing.zzhu | ⬆️ 27.8 kB | ⬆️ 10.4 kB |
🛸 Powered by Emerge Tools
Comment trigger: Size diff threshold of 100.00kB exceeded
e5fc244 to
3ce501a
Compare
> [!NOTE] > This targets branch `11.0-dev` which will become the epic branch for the upcoming major release. Once this first PR is merged, I'll open a continuous one from that one to `main` until we are ready to release it altogether. - Moves the SDK's build toolchain to AGP 9: | Dependency | From | To | |---|---|---| | AGP | 8.13.2 | **9.2.1** | | Gradle | 8.14.5 | **9.4.1** | | Kotlin | 2.0.21 | **2.2.21** | | Poko | 0.17.2 | **0.20.2** | | Paparazzi | 2.0.0-alpha02 | **2.0.0-alpha05** | - No public API change and no `api*.txt` diff. - **Why this becomes a major**: this transitively raises the miminum kotlin version for consumers to 2.1.0. up from 1.8.0. - Kotlin lands on **2.2.21, the minimum required by AGP 9**, - AGP is capped at **9.2.1** rather than latest: AGP 9.3.x requires Gradle 9.5+, and Gradle 9.5+ embeds a Kotlin that a 2.2 compiler cannot read, bumping consumers to an even higher minimum Kotlin version. - Nothing downstream needs AGP 9 or Gradle 9, just the Kotlin bump. The published AAR metadata is unchanged (`minCompileSdk=1`, `minAndroidGradlePluginVersion=1.0.0`). Companion docs PR: RevenueCat/docs PR 1942 Companion PHC PR: RevenueCat/purchases-hybrid-common PR 1844 - [ ] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids <details><summary>Agent description</summary> AGP 8 is increasingly behind, and AGP 9 removes a number of DSL surfaces we still used. The prerequisite work already landed separately in #3931, #3961 and #3963. AGP 9 has a runtime dependency on Kotlin Gradle Plugin **2.2.10 or higher**, so a Kotlin bump is not optional here. Everything above that floor is a choice, and this PR deliberately takes the minimum. An earlier revision of this branch used Kotlin 2.3.21. Measuring the cost changed the decision: - **It breaks every React Native consumer.** We publish `kotlin-stdlib` at `compile` scope and Gradle resolves consumers onto it. A compiler reads metadata at most one minor ahead. Kotlin 2.3.x publishes metadata 2.3.0, and React Native's own Gradle plugin pins the compiler: 2.0.21 through RN 0.79, 2.1.20 through RN 0.86, with only RN `main` on 2.2.0. Reproduced on a real RN 0.86 app: `metadata version is 2.3.0 / compiler version 2.1.0 can read versions up to 2.2.0`. Every RN app would have needed an explicit `kotlin-gradle-plugin` version in `android/build.gradle`. - **It forces the K2 migration.** Kotlin 2.3.21 rejects `languageVersion 1.8` outright. 2.2.x still accepts it, so the frontend migration stays out of a version bump where it does not belong. - **It does not avoid a second bump anyway.** Kotlin 2.4 removes `languageVersion 1.8` regardless. At Kotlin 2.2.21 the published metadata is 2.2.0, which RN 0.81+ reads untouched. This is the non-obvious constraint, and CI found it rather than local builds. `:codegen` is a `java-gradle-plugin` module, so it compiles against the Kotlin that **Gradle itself embeds**. Embedded Kotlin by Gradle release: | Gradle | Embedded Kotlin | Readable by a 2.2 compiler (max 2.3.0) | |---|---|---| | 9.3.1 | 2.2.21 | yes | | 9.4.1 | 2.3.0 | yes, exactly at the limit | | 9.5.1 | 2.3.20 | no | | 9.7.0 | 2.4.0 | no | Gradle 9.7.0 therefore failed `prepare-tests` with `metadata version is 2.4.0, but the compiler version 2.2.0 can read versions up to 2.3.0`. AGP 9.3.x requires Gradle 9.5.0 or higher (`Minimum supported Gradle version is 9.5.0`), which is exactly the range we cannot read. **AGP 9.2.1 is the newest release that runs on Gradle 9.4.1**; 9.1.1 and 9.0.1 were also confirmed to work, 9.3.1 was confirmed not to. So the AGP ceiling here is a consequence of the Kotlin floor, not an independent preference. When the deferred Kotlin 2.3 bump happens, AGP and Gradle can move up with it. - Standalone sample apps (`CustomEntitlementComputationSample`, `MagicWeather`, `MagicWeatherCompose`) move to Kotlin 2.2.21 and gain the `compose-compiler` plugin alias. They consume our published artifacts, so they need a compiler that can read our metadata. - Unit tests are re-enabled on the release variant via `HasUnitTestBuilder.enableUnitTest`, because AGP 9 only creates unit tests for the `testBuildType` variant and the published variant is release. - The `androidDependencies` cache-warm CI step is dropped; AGP 9 removed that task. - `migrations/v11-MIGRATION.md` documents the new Kotlin floor, mirroring the v9 guide. - README `Requirements` now says Kotlin 2.1.0+. - **Kotlin 2.3 and the K1 to K2 migration**, until React Native ships the KGP 2.2 pin already on its `main` branch. Doing it sooner buys nothing and costs every RN app a migration step. - **AGP 9 built-in Kotlin** (previously #3965). Not breaking and not required; the `android.builtInKotlin=false` / `android.newDsl=false` opt-out only has to go at AGP 10. - `assembleDebug` across all modules; release AARs for `:purchases` and `:ui:revenuecatui`. - `:purchases` unit tests, `:ui:debugview:verifyPaparazziDefaultsDebug`, `detektAll`. - `scripts/api-check.sh` with **zero** `api*.txt` diff. - Published contract checked directly: POM carries `kotlin-stdlib:2.2.21` at `compile` scope, the release AAR still reports `minCompileSdk=1` and `minAndroidGradlePluginVersion=1.0.0`, and our own classes carry metadata `mv = {1, 8, 0}`. - Consumer floor measured against the real release AAR plus the stdlib we publish: Kotlin 2.1.21 compiles; 2.0.21 and 1.9.24 fail. That is what the 2.1.0 claim in the README rests on. The Kotlin floor is what propagates, not AGP. Nothing downstream needs AGP 9 or Gradle 9. The only direct consumer is purchases-hybrid-common, which re-exposes us at compile scope via `api(libs.purchases)`. RevenueCat/purchases-hybrid-common PR 1844 raises its Kotlin accordingly, and the hybrid SDKs pick the floor up from there rather than from this repo. Documentation follows separately: - RevenueCat/docs PR 1942 adds the Kotlin minimum to the Android, Flutter and React Native installation pages, and adds the 9.x-to-10.x and 10.x-to-11.x migration guides the site was missing. - RevenueCat/purchases-flutter PR 1876 states the Kotlin minimum in that repo's README. Flutter applies the version from the app's `android/settings.gradle`, so the requirement lands on the consuming app and the Flutter version itself does not move. - RevenueCat/react-native-purchases PR 1925 raises the React Native floor to 0.80.0, the first release whose Gradle plugin pins a Kotlin that can read our metadata. </details> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Major toolchain and minimum Kotlin version changes affect all consumers and CI, though public API and published AAR AGP/minSdk metadata are intentionally unchanged. > > **Overview** > This PR moves the SDK build to **AGP 9.2.1**, **Gradle 9.4.1**, and **Kotlin 2.2.21**, and bumps related tooling (Poko, Paparazzi, baseline profile plugin). **`gradle.properties`** opts out of AGP 9’s built-in Kotlin and new DSL for now. > > The **consumer-facing change** is a higher Kotlin floor: README and **`migrations/v11-MIGRATION.md`** document **Kotlin 2.1.0+** (up from 1.8.0), driven by published stdlib metadata—not a public API change. > > **Build-logic** re-enables unit tests on library variants under AGP 9 via **`enableUnitTest`**, and keeps **`aarMetadata.minCompileSdk = 1`** so published AAR requirements don’t tighten. > > Compose sample apps switch to the **Kotlin Compose compiler plugin** and drop **`composeOptions.kotlinCompilerExtensionVersion`**. Several modules replace deprecated **`kotlinOptions`** with **`kotlin.compilerOptions.jvmTarget`**. > > **CircleCI** drops the removed **`androidDependencies`** warmup and uses Gradle cache restore on standalone sample builds instead. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1b6b4df. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Title says it all. This is to test downstream integrations <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Mechanical version string updates with no logic changes; only affects snapshot publishing, docs paths, and sample/test dependency pins for downstream integration testing. > > **Overview** > Bumps the Android SDK development version from **10.20.0-SNAPSHOT** to **11.0.0-SNAPSHOT** so the **11.0** branch publishes and documents under the new major line. > > **`gradle.properties`** `VERSION_NAME`, **`.version`**, and **`Config.frameworkVersion`** are updated together so Maven artifacts, runtime reporting, and release metadata stay aligned. CircleCI **docs-deploy** now syncs **`docs/11.0.0-SNAPSHOT`** to the matching S3 path. > > Example apps (Magic Weather, Magic Weather Compose, Custom Entitlement Computation) and **`test-apps/sdksizetesting`** pin **`purchases = "11.0.0-SNAPSHOT"`** in their version catalogs for integration and size testing against this snapshot. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8101201. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…e to AGP 9 (#4115) - Moves the two standalone sample builds, `MagicWeatherCompose` and `CustomEntitlementComputationSample`, to AGP 9.2.1 and Gradle 9.4.1, catching them up with the root build. - Both take the `android.builtInKotlin=false` and `android.newDsl=false` opt-out. #4120 removes it, stacked on top of this. Targets integration branch (`11.0-dev`) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Build-only version and Gradle property changes in example projects; no runtime or library code changes. > > **Overview** > Aligns the **MagicWeatherCompose** and **CustomEntitlementComputationSample** example builds with the root toolchain by bumping **AGP** from `8.13.2` to **`9.2.1`** and the Gradle wrapper from **`8.14.5`** to **`9.4.1`**. > > Each sample’s `gradle.properties` adds **`android.builtInKotlin=false`** and **`android.newDsl=false`** so existing **`kotlin-android`** plugin usage keeps working until a follow-up removes those opt-outs for AGP 10. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 16f5db0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
- Removes the `android.builtInKotlin=false` and `android.newDsl=false` opt-out that #3964 added, from the root build and from both standalone sample builds, and takes `kotlin-android` out of 11 build scripts and the 3 convention plugins. - `ui/debugview/api.txt` loses `InternalDebugRevenueCatScreenViewModelFactory`. Metalava now analyses the release variant, and that class lives in `src/debug/kotlin`. The release AAR contains zero occurrences of it, so it never shipped and the entry was wrong - Fixes `:dokkaGenerate`, which is already broken on `11.0-dev`. Built-in Kotlin registers Dokka source sets per Android variant instead of per Kotlin source set, and registers them lazily, so both `:purchases` and `:ui:revenuecatui` now select the documented variant through `configureEach`. - Bumps `androidx.navigation` 2.5.3 to 2.9.8. safeargs 2.5.3 detects AGP through the old DSL and hard fails, so the navigation bump is a prerequisite for the new DSL rather than an independent upgrade. ### Checklist - [ ] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids <details><summary>Agent description</summary> ### Motivation AGP 9 enables built-in Kotlin and rejects the `org.jetbrains.kotlin.android` plugin outright: ``` The 'org.jetbrains.kotlin.android' plugin is no longer required for Kotlin support since AGP 9.0. ``` Opting out needs two flags together, `android.builtInKotlin=false` and `android.newDsl=false`, because the kotlin-android plugin casts the android extension to `BaseExtension`, which the new DSL drops. #3964 took that opt-out so the version bump stayed reviewable. AGP 10 removes the opt-out, so the migration has to happen regardless; doing it separately keeps the two diffs legible. ### Description Four things blocked the migration, each hidden behind the previous. **The old DSL extension types are gone.** `com.android.build.gradle.BaseExtension` and `com.android.build.gradle.LibraryExtension` do not exist once the new DSL is active. The convention plugins now configure `com.android.build.api.dsl.ApplicationExtension` and `com.android.build.api.dsl.LibraryExtension`, and set `compileSdk` directly rather than calling `compileSdkVersion()`. `KotlinAndroidProjectExtension` stays as is: AGP's built-in Kotlin still registers it. **safeargs 2.5.3 cannot see AGP 9.** It fails with `safeargs plugin must be used with android plugin`, because its detection goes through the old DSL. The 2.5.3 jar references `com/android/build/gradle/BaseExtension`, `AppExtension` and `gradle/api/BaseVariant`; the 2.9.8 jar references only `com.android.build.api.variant.*`. `examples/purchase-tester` is the only module applying the plugin, and it gets its own commit. **Dokka source sets changed shape.** With the kotlin-android plugin, Dokka saw the Kotlin source sets and the config addressed `main`, `defaults` and `customEntitlementComputation`. Built-in Kotlin instead registers one source set per Android variant, and registers them after the `dokka { }` block runs, so `named("defaultsRelease")` throws even though the name is valid later. Both modules now select through `matching { }.configureEach`. `:purchases` keeps `reportUndocumented`, `skipDeprecated`, the Android external documentation link, both source links and the `paywalls.components` suppression, all moved onto the selected variant. The explicit `customEntitlementComputation` suppression is load-bearing, not redundant: Dokka defaults `suppress` to `!isPublishable` and `customEntitlementComputationRelease` is published, so it would otherwise be documented. **`kotlin-test` stops carrying JUnit.** `:feature:galaxy` names `kotlin-test-junit` instead. Verified rather than inherited: with plain `kotlin-test`, `org.junit.Test` is unresolved across all 25 test methods. **Not visible in the diff:** `./gradlew :dokkaGenerate` fails on the base commit with `Dokka cannot generate documentation for Android projects with multiple enabled variants that have common source roots`. The `docs-deploy` job that runs it is gated on release tags, so #3964 never exercised it. This PR is what makes it pass again, which is a bigger deal than the diff makes it look. **Worth noting separately:** AGP 9.2.1 declares `kotlin-gradle-plugin:2.2.10`, so built-in Kotlin takes its compiler from buildscript classpath resolution rather than from our catalog. Confirmed the published contract from #3964 is intact rather than assumed: | check | result | | --- | --- | | resolved KGP | `2.2.21`, not AGP's bundled `2.2.10` | | `:purchases` POM | `kotlin-stdlib:2.2.21` at `compile` scope | | release AAR metadata | `mv=[1,8,0]`, so `languageVersion` 1.8 survives | ### Regression gates - `./gradlew :dokkaGenerate` for the Dokka rework. Generates 1367 pages with `com.revenuecat.purchases.paywalls.components` still suppressed. - `:feature:galaxy:testDefaultsDebugUnitTest` for the `kotlin-test-junit` swap. Needs `--rerun-tasks`: a cached run passes even with the dependency reverted, which is how this could slip through. - `:examples:purchase-tester:assembleDebug` for the navigation bump. **Rejected:** - Wiring the Dokka variant selector to `ANDROID_VARIANT_TO_PUBLISH` instead of hardcoding `"defaultsRelease"` twice. `fastlane/Fastfile:295` rewrites that property per publish, so a `customEntitlementComputation` publish would point Dokka at exactly the variant `:purchases` suppresses. - Hoisting the shared Dokka config into `ConfigureDokka.kt`. Dokka's types are not on build-logic's compile classpath, so it needs the reflection pattern from `ConfigureMetalava.kt`, and sharing `reportUndocumented.set(true)` would newly turn it on for the four public-library modules that have no `dokka { }` block. - Moving the five hand-rolled app modules onto `revenuecat-android-application`, which would collapse 5 of the 6 per-module edits. Each keeps 2 to 3 overrides, and both `testpurchases*` modules deliberately pin old `compileSdk`/`targetSdk` to test compatibility. Worth a separate PR, not this one. **Limitations:** - `examples/MagicWeather` and `test-apps/sdksizetesting` still apply `kotlin-android`. They are separate builds pinned to AGP 8.13.2, so they keep the plugin correctly and are untouched. - `purchases/build.gradle.kts:120` has a dead `androidComponents { onVariants }` block guarding a `"free"` product flavor that does not exist in the repo. Pre-existing and unrelated, left alone. </details> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Wide Gradle/AGP convention changes affect every Android module’s compile and doc generation; navigation and Dokka behavior are prerequisites for CI release docs, with limited runtime SDK impact. > > **Overview** > Completes the AGP 9 migration by removing the **`android.builtInKotlin=false`** / **`android.newDsl=false`** opt-outs and dropping **`org.jetbrains.kotlin.android`** across convention plugins, app modules, samples, and the version catalog. > > Build-logic now configures **`ApplicationExtension`** / **`LibraryExtension`** from the new DSL (e.g. **`compileSdk`** instead of **`BaseExtension`**). **`:purchases`** and **`:ui:revenuecatui`** Dokka blocks use **`matching { }.configureEach`** so documentation targets **`defaultsRelease`** and suppresses **`customEntitlementComputation`** variants after AGP registers per-variant source sets lazily. > > **`androidx.navigation`** is bumped **2.5.3 → 2.9.8** so Safe Args works with the new DSL. **`:feature:galaxy`** switches unit tests to **`kotlin-test-junit`**. **`ui/debugview/api.txt`** drops **`InternalDebugRevenueCatScreenViewModelFactory`** (debug-only; not in the release API Metalava analyzes). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e45c589. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Moves `sdksizetesting` to the new AGP version. Targets `11.0-dev` integration branch <!-- CURSOR_SUMMARY --> --- > [!NOTE] > <sup>[Cursor Bugbot](https://cursor.com/bugbot) is generating a summary for commit afd111d. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Temporary while 11.0-dev is WIP, so we can test it out in PHC and hybrids. we'll remove it before merge <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > CI-only branch filter change for snapshot publishing; no application or release logic changes, and the extra branch is explicitly temporary. > > **Overview** > **Temporarily** extends the `snapshot-deploy-sample-app-tests` CircleCI workflow so it runs on **`11.0-dev`** as well as **`main`**, not only on `main`. > > That workflow still deploys Maven snapshots (`deploy-snapshot`) and then builds sample apps that depend on those artifacts. The branch gate is now an `or` on `main` / `11.0-dev`, with a **TODO** to remove the `11.0-dev` branch before merging that line into `main`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 41cdc50. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
- Bumps Play Billing Library from 8.3.0 to 9.1.0. Targets `11.0-dev`.
- **BC9 pulls in `androidx.core` 1.15.0, which requires every consuming
module to use compileSdk 35 or higher.** This breaks compilation for
consumers. I've also updated it in `libs.versions.toml` to be explicit.
- Only behaviour change: When the Play Store is blocked by the system
(kids mode), BC9 returns `BILLING_UNAVAILABLE` instead of `ERROR`, so
apps now get `PurchaseNotAllowedError` instead of `StoreProblemError`
there. I couldn't reproduce this since it's not configurable on
devices/emulator, would require a custom OS build.
- No public API changes.
- Tested (license tester):
- Consumable purchase
- Consumable repurchase
- Non-consumable
- Subscription
- Prorated switch
- Pending purchase
- User cancel
- Restore
- Store unavailable
- Own-IAP-code mode (SDK only syncs)
### Checklist
- [x] If applicable, unit tests
- [ ] If applicable, create follow-up issues for `purchases-ios` and
hybrids
<details><summary>Agent description</summary>
### Motivation
Play Billing Library 9.0.0 (May 2026) and 9.1.0 (June 2026) are out. The
release notes list no removals, but diffing the 8.3.0 and 9.1.0 AARs
shows `SkuDetails`, `SkuDetailsParams`, `SkuDetailsResponseListener`,
`BillingClient.SkuType`, `BillingFlowParams.Builder.setSkuDetails` and
`QueryPurchaseHistoryParams` are gone, and the POM gains
`androidx.core:core:1.15.0` (`minCompileSdk=35` in its aar-metadata).
That makes the bump breaking for consumers on compileSdk 34, so it rides
the v11 major.
### Description
- `billingClient` 8.3.0 to 9.1.0 in the version catalog.
- Removed `buildQueryPurchaseHistoryParams` (no callers since the BC8
migration) and the unused `SkuDetails` parameter in the api-tester.
- BC 9.x changed the public `InAppMessageResult(int, String)`
constructor to ignore its arguments and always yield `NO_ACTION_NEEDED`.
The SDK never constructs that class, so this is test-only; the two
in-app message tests in `BillingWrapperTest` now mock the result.
- Compatibility test apps and `baselineprofile` move from compileSdk 34
to 35, the new floor they should verify.
- `migrations/v11-MIGRATION.md` gains sections for BC9, the compileSdk
requirement (with the `checkDebugAarMetadata` error text, captured by
building a test app at compileSdk 34), the blocked-Play-Store error
change, and the own-IAP-code note.
- Out of scope: Billing Choice program and dynamic product token APIs
added in 9.x.
</details>
…7.3 (#4258) Paywalls whose localizations contain images fail to parse on `11.0-dev`. This fixes that and makes the catalog say what consumers actually resolve. - `11.0-dev` is affected today, `main` is not. `androidx.savedstate` already forces kotlinx-serialization 1.7.3 onto any consumer app classpath on the major branch, while `main` still resolves 1.5.1. No released version is affected. - 1.7.3 no longer rewinds the streaming decoder after a failed `decodeSerializableValue`. `LocalizationDataSerializer` picks between `Text` and `Image` by trial and error, so the failed `Text` attempt left the lexer past the opening brace and every `Image` retry failed. - The catalog pinned 1.5.1, which is why no test caught it: `:purchases` resolves 1.5.1 in isolation, so its own test run never saw the version apps get. - The trial and error is deliberately unchanged. Only the source it reads from changed, from the stream to a re-readable `JsonElement`. - Found while raising the same pin in #4253. That PR does not cause this break and no longer carries the fix. ### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids <details><summary>Agent description</summary> ### Motivation `LocalizationData` is a make-shift union: a localization value is either a plain string or a `ThemeImageUrls` object, with no `type` discriminator on the wire. The serializer resolved that by trying `Text` first and falling back to `Image` on `SerializationException`. That works only if a failed attempt leaves the decoder where it started. kotlinx-serialization 1.7.3 does not put it back, so the fallback starts mid-token. For input beginning `{ "light": ...`, the `Text` attempt consumes the `{` and the `Image` retry fails at offset 4 on the `"` of `"light"`. Verified by resolving `examples/paywall-tester`'s `debugRuntimeClasspath`: | ref | kotlinx-serialization | | :--- | :--- | | `main` | 1.5.1 | | `11.0-dev` | 1.7.3 | ### Description - Decodes the element once through `JsonDecoder.decodeJsonElement()`, then runs the same two serializers against it. A `JsonElement` can be read repeatedly, so the fallback sees the whole value. - Guards the decoder cast with `as?` and a `SerializationException`, matching the other custom serializers in the module rather than risking a `ClassCastException` from a bare cast. - Pins `kotlinxSerializationJSON` to 1.7.3. This is what makes `LocalizationDataTests > Should properly deserialize LocalizationData[ThemeImageUrls]` a regression gate: with the pin and without the fix it fails, which is how the break was confirmed on a branch carrying no other change. - Updates the `WebViewContextSnapshotTest` fixture, since 1.7.3 pretty-prints empty objects as `{}` rather than `{\n}`. Production does not pretty-print, so the wire payload is unchanged. #4253 carries the same fixture change because it reaches 1.7.3 by a different route; whichever lands second will find it already applied. Worth a follow-up, pre-existing and untouched here: `LocalizationDataSerializer` never attempts `LocalizationData.Video`, only `Text` then `Image`, though `Video` is a member of the sealed interface. </details> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches paywall JSON deserialization for all localizations and aligns the build to 1.7.3; behavior change is limited to fixing broken image parsing, but parsing is on the critical paywall load path. > > **Overview** > Fixes paywall parsing when localizations include **image** values under **kotlinx-serialization 1.7.3**, which apps on `11.0-dev` already resolve via transitive deps while the catalog still pinned 1.5.1. > > **`LocalizationDataSerializer`** still picks `Text` vs `Image` by trial and error, but it now reads a full **`JsonElement`** once and retries against that buffer. In 1.7.3 a failed stream decode no longer rewinds, so the old fallback started mid-object and broke `ThemeImageUrls` payloads. > > The version catalog bumps **`kotlinxSerializationJSON` to 1.7.3** so module tests exercise the same serializer behavior as consumer apps. **`WebViewContextSnapshotTest`** updates expected pretty-printed JSON for an empty `inputs` object (`{}` vs multiline `{\n}`); wire format is unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a530a5f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
> this targets the next major branch (11.0-dev)
Updates the Compose BOM from `2024.09.00` to `2026.06.01` (Compose
1.11.4) for SDK-4243.
- `material-icons` now needs explicit declaration. Compose stopped
publishing it after 1.7.8 and `material` 1.8.0 dropped its dependency on
it, so apps that reached `Icons.Default.*` transitively through
RevenueCatUI now have to declare it themselves. That is the small
breaking part of this PR.
- Stops at Compose 1.11.4, not the latest. The 1.12 line requires
compileSdk 37 and JVM target 11, which we are not tackling in this
major.
- Compose 1.11 ships lint checks this module does not satisfy so they
are baselined
- [x] If applicable, unit tests
- [ ] If applicable, create follow-up issues for `purchases-ios` and
hybrids
<details><summary>Agent description</summary>
### Motivation
The BOM had not moved in two years. It is pinned in the `11.0-dev` major
branch, which is the only place the consumer-facing fallout is
acceptable.
Three separate removals land at once, which is why the diff touches more
than a version number:
1. `materialIcon` and `materialPath`, the builders the SDK's own
hand-drawn vectors were written against, went away with
`material-icons`.
2. `Icons.*` stopped arriving transitively through `compose-material`.
3. New lint checks turned previously clean code into 33 errors.
### Description
- Reimplements `materialIcon` and `materialPath` locally in
`MaterialIcon.kt`, so the 7 icon files in `revenuecatui` keep their path
DSL bodies and only lose an import. `revenuecatui` has no reference to
`androidx.compose.material.icons` left.
- Declares `material-icons-core` on the 6 sample and test apps that use
`Icons.*` for their own chrome, mostly back arrows and toolbar
affordances. No version: the BOM still pins it at 1.7.8, its last
published version, so it will not move again.
- Updates one test fixture. The BOM pulls kotlinx-serialization to 1.7.3
through `androidx.savedstate`, and 1.7.3 pretty-prints empty objects as
`{}` instead of `{\n}`, which changes `WebViewContextSnapshotTest`.
Production does not pretty-print, so the wire payload is unchanged.
#4258 carries the same fixture change, since it reaches 1.7.3 by a
different route.
- Adds `ui/revenuecatui/lint-baseline.xml`. Lint is clean on `11.0-dev`
without this PR, so all 33 errors are new checks rather than
pre-existing debt.
Split into commits so the two icon problems read separately from the
bump itself.
The same 1.7.3 jump breaks paywall image localization parsing. That is
already broken on `11.0-dev` without this PR, so it is fixed separately
in #4258 rather than here.
</details>
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Wide Compose stack upgrade can affect paywall UI and serialization
behavior; consumer apps must add `material-icons-core` if they relied on
transitive icons from RevenueCatUI.
>
> **Overview**
> Bumps the **Compose BOM** from `2024.09.00` to **`2026.06.01`**
(Compose 1.11.x) across the repo via `gradle/libs.versions.toml`.
>
> **Material icons fallout:** Compose no longer pulls in
`material-icons` transitively, so the PR adds a
**`compose-material-icons-core`** catalog entry and declares it on
sample/e2e apps that use `Icons.*` in their own UI. **`revenuecatui`**
drops `androidx.compose.material.icons` entirely by adding local
**`MaterialIcon.kt`** helpers (`materialIcon` / `materialPath`) so
existing hand-drawn icon vectors keep the same path DSL with only import
changes.
>
> **Lint:** `ui/revenuecatui` wires **`lint-baseline.xml`** and checks
in a large baseline so new Compose 1.11 lint rules do not fail the
module (existing patterns like WebView APIs, `Configuration.screen*Dp`,
preview ViewModels, etc. are grandfathered—not fixed in this PR).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2c2b626. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Raises the kotlinx-coroutines pin from 1.6.4 to 1.9.0, so the SDK is tested against the version its users actually run. - Raises the floor for apps that use `purchases` alone (without ui), from 1.6.4 to 1.9.0. That is the one consumer-facing consequence, and the reason this belongs in a major. - Apps including RevenueCatUI resolve 1.7.3 today, and 1.9.0 once the Compose BOM moves in #4253. For them this changes nothing, it only makes the catalog say so. - Same class of problem as #4258, found the same way, but this one doesn't have a bug, just putting it in the correct version to prevent one in the future. ### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids <details><summary>Agent description</summary> ### Motivation `#4258` fixed a paywall parsing break caused by a dependency the catalog claimed to pin at one version while consumers resolved another. Auditing the rest of the graph for the same shape turned up coroutines as the largest remaining case: the catalog said 1.6.4, a two-year-old version, while real apps ran something newer. Resolved `debugRuntimeClasspath` on `11.0-dev`: | consumer | kotlinx-coroutines | | :--- | :--- | | `test-apps/testpurchasesandroidcompatibility`, purchases only | 1.6.4 | | `examples/paywall-tester`, includes RevenueCatUI | 1.7.3 | | the same app with the Compose BOM of #4253 | 1.9.0 | Unlike #4258 the catalog was not lying to every consumer: a purchases-only app really does get 1.6.4. The gap is that the SDK's unit tests have never run against what the majority of apps resolve, which is exactly the blind spot that hid the #4258 break until the pin was corrected. ### Description - One line in `gradle/libs.versions.toml`. `coroutines-core`, `coroutines-android` and `coroutines-test` all share the version ref, so the test dependency moves with the runtime one. - Verified by running `purchases:testDefaultsDebugUnitTest`, `purchases:testCustomEntitlementComputationDebugUnitTest`, `ui:revenuecatui:testDefaultsDebugUnitTest`, `detektAll`, `lint` and `testClasses` against 1.9.0 on an otherwise unmodified `11.0-dev`. Independent of #4253 and #4258. All three branch from `11.0-dev` and touch different lines; they can land in any order. </details> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Raising the pinned coroutines version affects runtime and test dependencies across `purchases` and raises the minimum for purchases-only apps, though the change is limited to one catalog entry and was validated with the usual test/lint tasks. > > **Overview** > Aligns the Gradle version catalog with the coroutines version many apps already resolve, and moves SDK unit tests onto that same line. > > The **`coroutines`** pin in `gradle/libs.versions.toml` goes from **1.6.4 → 1.9.0**, which also updates **`coroutines-core`**, **`coroutines-android`**, and **`coroutines-test`** because they share that ref. For integrators that depend on **`purchases` only** (no RevenueCat UI), the effective minimum coroutines version the SDK pulls in rises to 1.9.0—a consumer-facing floor change called out for a major release. Apps that already get a newer coroutines transitively via UI/Compose should mostly see the catalog catching up, not a behavior change. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9c498ca. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
afe213b to
107e81e
Compare



PR grouping all of the upcoming 11.0 breaking release changes
Note
High Risk
Major toolchain and version-line release (Kotlin metadata floor, AGP 9) affects every consumer build; integrators on Kotlin < 2.1 will fail until they upgrade.
Overview
v11 bumps the SDK to 11.0.0-SNAPSHOT and retargets the whole repo on AGP 9.2.1, Kotlin 2.2.21, and Gradle 9.4.1, with documented Kotlin 2.1.0+ minimum for integrators (
migrations/v11-MIGRATION.md, README).Build conventions move to AGP 9 APIs (
ApplicationExtension/LibraryExtension), drop explicitorg.jetbrains.kotlin.androidfrom convention plugins and rootapply falsewiring, and adjust libraries for AGP 9 (aarMetadata.minCompileSdk = 1,enableUnitTestvia variant API). Compose samples switch to the Kotlin Compose compiler plugin and removecomposeOptions.kotlinCompilerExtensionVersion; JVM targets move fromkotlinOptionstokotlin { compilerOptions }. Dokka source sets use lazymatchingon flavor variants instead of fixednamedsets.CI/docs: removes the shared
android-dependenciesGradle prefetch in favor ofrestore_gradle_cacheon sample builds, publishes docs to11.0.0-SNAPSHOT, and runs snapshot + sample-app workflow on11.0-devas well asmain(temporary TODO).ui/debugviewpublic API dump dropsInternalDebugRevenueCatScreenViewModelFactory.Reviewed by Cursor Bugbot for commit 7128063. Bugbot is set up for automated code reviews on this repo. Configure here.