feat(android): update for 2.8.0 - #253
Conversation
Bumps documented Android SDK version from 2.7.23 to 2.8.0. - content/docs/android/index.mdx: SdkLatestVersion 2.7.23 -> 2.8.0 - content/docs/android/sdk-reference/index.mdx: SdkLatestVersion 2.7.23 -> 2.8.0 - content/docs/android/quickstart/install.mdx: Gradle/KTS/TOML install snippets bumped to 2.8.0; added a Warning about the minSdk 21 -> 23 requirement introduced by the Play Billing Library 9.1.0 upgrade. - content/docs/android/changelog.mdx: inserted the upstream 2.8.0 entry verbatim above 2.7.23, preserving all historical entries (Enhancements, Breaking Changes, minSdk notice, Deprecations). - content/docs/android/sdk-reference/PurchaseController.mdx: updated the purchase() signature to include the basePlanId/offerId params it has taken since before this release (was previously stale/incomplete in the docs), documented the new default StoreProduct-based overload introduced in 2.8.0, and added a "Custom store products" section covering product.isCustomProduct / customTransactionId per the upstream changelog. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b55a60ae30
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ``` | ||
|
|
||
| <Info> | ||
| Starting in `2.8.0`, `purchase()` receives a `StoreProduct` (instead of the Billing Library's `ProductDetails`), which also supports [custom store products](#custom-store-products). For Google Play products, the underlying `ProductDetails` is available via `product.rawStoreProduct`. The default implementation of this method routes Google Play products to the older `purchase(activity, productDetails, basePlanId, offerId)` overload, so existing implementations of that overload keep working unchanged. That older overload is now deprecated; implement the `StoreProduct`-based method above going forward, and implement it directly if you need to support custom store products. |
There was a problem hiding this comment.
Update the implementation guides for the new overload
When developers follow the linked implementation guidance, both content/shared/advanced-configuration.mdx:190-195 and the Android section of content/shared/using-revenuecat.mdx:266-271 still implement the deprecated ProductDetails overload. That remains usable for Play products, but, as this callout explains, it cannot receive custom store products, so users following these examples cannot implement the newly documented custom-product flow. Update the shared Android samples to override the StoreProduct method and handle or explicitly reject the custom-product branch.
Useful? React with 👍 / 👎.
| Products configured on a custom store in the Superwall dashboard (e.g. Stripe or your own payment backend) can be attached to paywalls. Their metadata (price, subscription period, trial) is fetched from the Superwall API instead of Google Play, and purchases for them are routed through your `PurchaseController`, bypassing Google Play Billing entirely. | ||
|
|
||
| - Check `product.isCustomProduct` in `purchase()` to detect a custom product and fulfill it via your own payment flow. | ||
| - On a successful purchase, grant the entitlement yourself by calling `Superwall.instance.setSubscriptionStatus(...)` — the SDK does not do this automatically for custom products. |
There was a problem hiding this comment.
Separate entitlement fulfillment from status synchronization
For a custom-backend purchase, setSubscriptionStatus(...) only reports the entitlements that the app's purchase system has already granted; it does not fulfill or persist the purchase itself. The existing API reference at content/docs/android/sdk-reference/advanced/setSubscriptionStatus.mdx:10-15 explicitly describes this as keeping Superwall synchronized with the purchase system, but this new instruction—and the equivalent wording in the new changelog entry—tells developers to grant the entitlement by calling it. A developer following that literally can mark the current client active without provisioning the user's account in their backend. Instruct users to grant access in their own billing/backend system first, then call setSubscriptionStatus(...) to mirror the resulting entitlement state into Superwall.
Useful? React with 👍 / 👎.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
superwall-docs | 50bc76d | Commit Preview URL Branch Preview URL |
Aug 03 2026, 07:47 PM |
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, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0880d06. Configure here.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0880d06a66
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ``` | ||
|
|
||
| <Info> | ||
| Starting in `2.8.0`, Kotlin's `PurchaseController.purchase()` receives a `StoreProduct` (instead of the Billing Library's `ProductDetails`), which also supports [custom store products](#custom-store-products). For Google Play products, the underlying `ProductDetails` is available via `product.rawStoreProduct`. The default implementation of this method routes Google Play products to the older `purchase(activity, productDetails, basePlanId, offerId)` overload, so existing implementations of that overload keep working unchanged. That older overload is now deprecated; implement the `StoreProduct`-based method above going forward, and implement it directly if you need to support custom store products. |
There was a problem hiding this comment.
Reference the actual ProductDetails property
When developers use this note to migrate a Google Play implementation, rawStoreProduct is the SDK wrapper rather than the underlying Billing Library ProductDetails; the updated examples correctly unwrap product.rawStoreProduct?.underlyingProductDetails (for example, content/shared/using-revenuecat.mdx:278-280). Stating that the ProductDetails is available directly through product.rawStoreProduct leads readers to pass the wrong type, so document the full property path here.
Useful? React with 👍 / 👎.
| onBackPressed: { | ||
| type: "((PaywallInfo?) -> Boolean)?", | ||
| description: "Callback invoked when back button is pressed (requires `reroute_back_button` enabled in paywall settings). Return `true` to consume the back press, `false` to use SDK default behavior.", | ||
| description: "Callback invoked when back button is pressed (requires `reroute_back_button` enabled in paywall settings). Return `true` to consume the press. Return `false` to forward it to the paywall as `back_button_input`; the paywall navigates back one page when possible or closes through its standard manual-close path.", |
There was a problem hiding this comment.
Document the legacy-paywall back-press behavior
When an app still presents a paywall built on a runtime that predates back_button_input, returning false does not navigate or close the paywall—the press is ignored, as the new 2.8.0 changelog entry explains at content/docs/android/changelog.mdx:16. This unconditional description can therefore leave existing paywalls with an apparently broken back button; include the old-runtime caveat and tell users to republish affected paywalls.
Useful? React with 👍 / 👎.
| <Warning> | ||
| Starting with `2.8.0`, the SDK requires **`minSdk` 23** (previously 21) because it upgrades the underlying Google Play Billing Library to 9.1.0. If your app's `minSdk` is below 23, raise it before upgrading. Because Billing is resolved to a single version across your app, this also upgrades Billing for any other library that depends on it (RevenueCat, Adapty, Purchasely, etc.) — confirm those providers support Billing 9 before shipping. See the [changelog](/android/changelog) for the full breaking-changes list and a workaround if you need to pin Billing to version 8. | ||
| </Warning> |
There was a problem hiding this comment.
Update the Unity Android dependency guidance
For fresh Unity Android builds, content/docs/unity/quickstart/install.mdx:54-55 still says the package pulls superwall-android:2.+ alongside Billing 8.0.0. That dynamic SDK selector now resolves 2.8.0, whose transitive Billing 9.1.0 dependency wins Gradle conflict resolution, so Unity users actually receive the same Billing upgrade described here while their installation page continues to promise Billing 8 and omits the compatibility warning. Update the Unity dependency list and add the relevant Billing 9 migration guidance there as part of this release sync.
Useful? React with 👍 / 👎.

Summary
previousVersion->newVersion:2.7.23->2.8.0Upstream references
reference/android/CHANGELOG.md(## 2.8.0section), copied verbatim intocontent/docs/android/changelog.mdx.Key upstream changes in this release:
SkuDetails/purchase-history APIs).minSdkraised 21 -> 23 as a consequence of the Billing 9 requirement.PurchaseController.PurchaseController.purchase(activity, product: StoreProduct, basePlanId, offerId)method; the previousProductDetails-based overload is deprecated but still works via a default implementation.back_button_inputinstead of dismissing directly (multi-page paywalls navigate back a page; single-page paywalls dismiss as before).Checklist of doc updates performed
content/docs/android/index.mdx:<SdkLatestVersion version="2.7.23" .../>->2.8.0content/docs/android/sdk-reference/index.mdx:<SdkLatestVersion version="2.7.23" .../>->2.8.0content/docs/android/quickstart/install.mdx: Gradle/Kotlin DSL/libs.versions.tomlsnippets bumped to2.8.0; added a<Warning>documenting the newminSdk23 requirement and the Billing-Library-9 upgrade impact (with a link to the changelog for the pin-to-Billing-8 workaround).content/docs/android/changelog.mdx: inserted the full upstream## 2.8.0entry verbatim directly above## 2.7.23, preserving all existing historical entries (additive only, nothing removed/replaced).content/docs/android/sdk-reference/PurchaseController.mdx: updated thepurchase()signature (Kotlin + Java) to includebasePlanId/offerId(the docs were previously stale even pre-2.8.0, missing these params entirely), added an info callout on the newStoreProduct-based overload and its default-routing/deprecation behavior, and added a new "Custom store products" section documentingproduct.isCustomProduct,StoreProduct.customTransactionId, and thesetSubscriptionStatus(...)entitlement-granting requirement for custom products.Verification
bun run download:references— OKbun test— 64 pass / 0 failbun run lint— 0 errors (13 pre-existing warnings inplugins/*.ts/config files, unrelated to this change)bun run build:cf— fails in this sandbox on OG-image generation (generate:og) for an unrelatedexpodoc page with a Vite SSR transport timeout / OOM kill during production chunk rendering. Confirmed this reproduces identically on a clean, unmodifiedmaincheckout (stashed my changes and re-ran), so it's a pre-existing sandbox resource constraint (only ~3.8GB RAM available vs. the 5GB--max-old-space-sizethe build script requests), not caused by this PR. All 5 changed files were also checked for balanced custom MDX component tags (Warning/Info/CodeGroup/etc.) and code fences — all balanced. Recommend re-runningbun run build:cfin CI/a properly resourced environment before merge.Follow-up / known gaps
PurchaseControllercode snippets (incontent/docs/android/quickstart/tracking-subscription-state.mdxandcontent/docs/android/sdk-reference/advanced/setSubscriptionStatus.mdx) still show a 2-argpurchase(activity, product: StoreProduct)override that doesn't match either the pre- or post-2.8.0 real interface. This inconsistency predates 2.8.0 (it was already stale relative to thebasePlanId/offerIdparams added earlier) and both snippets already point readers to the canonical, accurate example in Using RevenueCat for real implementations, so it was left out of scope for this version-bump PR. Worth a follow-up cleanup pass.🤖 Generated with Claude Code
Note
Low Risk
Documentation-only changes with no runtime or auth impact; reviewers should confirm code samples match the released 2.8.0 APIs.
Overview
Updates the docs site for Superwall Android SDK 2.8.0 (from 2.7.23): version badges, Gradle install snippets, and a full 2.8.0 changelog entry covering Play Billing 9, minSdk 23, custom store products, and back-button behavior.
Install & platform notes: Adds a warning on the Android install page about minSdk 23 and app-wide Billing 9 resolution (with a link to pin Billing 8). Unity Android install docs now note Billing 9.1.0 and the same constraints when
2.+resolves to 2.8.0.API & guides: Documents
PurchaseController.purchase(..., StoreProduct, basePlanId, offerId), custom products (isCustomProduct,rawStoreProduct,customTransactionId), and a Custom store products section.setSubscriptionStatus(vararg entitlements: String)andSubscriptionStatus.Active(Set<Entitlement>)are reflected across subscription-status and PurchaseController docs.PaywallOptions.onBackPressedis updated forback_button_inputforwarding. Shared RevenueCat, advanced purchasing, and paywall examples are aligned with the new purchase signature and result types (PurchaseResult.Purchased(), etc.).Reviewed by Cursor Bugbot for commit 50bc76d. Bugbot is set up for automated code reviews on this repo. Configure here.