fix: ensure activity is attached before showing in-app messages#3274
Merged
tonidero merged 1 commit intoMar 25, 2026
Conversation
tonidero
reviewed
Mar 25, 2026
tonidero
left a comment
Contributor
There was a problem hiding this comment.
Thank you for the contribution!
Left a question in the issue, to make sure this is needed. Other than that, it would be great to have a test for this new case :)
Thanks again!
8f092a2 to
af9df05
Compare
tonidero
approved these changes
Mar 25, 2026
tonidero
left a comment
Contributor
There was a problem hiding this comment.
Amazing, thanks for adding those tests and thanks again for the contribution! We will get this merged and will be part of our next release 👍
d3a5a90
into
RevenueCat:external/matteinn/fix/#3273-showinappmessagesifneeded-crash
1 check passed
2 tasks
github-merge-queue Bot
pushed a commit
that referenced
this pull request
Mar 25, 2026
…sages (#3274) contributed by @matteinn (#3275) <!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> ### Checklist - [ ] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation This PR adds an additional safety check in BillingWrapper.showInAppMessagesIfNeeded to ensure the activity is fully attached to a window before attempting to show Google Play in-app messages, preventing crashes. Resolves #3273. ### Description While `isFinishing` and `isDestroyed` are already checked, `NullPointerException` crashes can still happen while accessing a window token from a null or detached view. Using `peekDecorView().windowToken` safely ensures the activity has a decor view and is attached [without accidentally triggering view creation](https://developer.android.com/reference/android/view/Window#peekDecorView()). contributed by @matteinn in #3274 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk guard change that only adds an extra precondition before invoking Google Play Billing in-app messages; main impact is potentially skipping message display in edge lifecycle states to avoid crashes. > > **Overview** > Prevents crashes when showing Google Play in-app messages by adding an additional lifecycle safety check in `BillingWrapper.showInAppMessagesIfNeeded`: it now verifies the `Activity` is attached to a window via `activity.window?.peekDecorView()?.windowToken` before calling `showInAppMessages`. > > Updates `BillingWrapperTest` to use a reusable `mockAttachedActivity()` helper and adds coverage to ensure in-app messages are *not* shown when the window, decor view, or window token are missing. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d3a5a90. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Matteo Innocenti <matteo@appstyx.com>
github-merge-queue Bot
pushed a commit
that referenced
this pull request
Mar 26, 2026
**This is an automatic release.** ## RevenueCat SDK ### 🐞 Bugfixes * [EXTERNAL] fix: ensure activity is attached before showing in-app messages (#3274) contributed by @matteinn (#3275) via Toni Rico (@tonidero) * Ensure MediaPlayer has dedicated thread owner that is not the main thread (#3148) via Jacob Rakidzich (@JZDesign) * Fix heartbeat monitor and Slack notifications for nightly integration tests (#3259) via Rick (@rickvdl) ## RevenueCatUI SDK ### Paywallv2 #### ✨ New Features * Feat: Restore gating in paywalls UI (#3171) via Jacob Rakidzich (@JZDesign) ### 🔄 Other Changes * security: pin GitHub Actions to SHA hashes (#3272) via Alfonso Embid-Desmet (@alfondotnet) * Bump activesupport from 8.0.2 to 8.0.4.1 (#3270) via dependabot[bot] (@dependabot[bot]) * Merge release PR after deploy (#3269) via Antonio Pallares (@ajpallares) * Require PR approval before release tagging (#3268) via Antonio Pallares (@ajpallares) * Bump json from 2.18.1 to 2.19.2 (#3261) via dependabot[bot] (@dependabot[bot]) * feat(ads): update admob sample app (#3264) via Peter Porfy (@peterporfy) * feat(ads): add vanilla-ad-tracker-sample (#3263) via Peter Porfy (@peterporfy) * [Purchase Tester]: Persist appUserId on login screen across app launches (#3266) via Will Taylor (@fire-at-will) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Mostly release automation and versioning changes, but it modifies CI/orb references and deploy/merge automation, which could affect the release pipeline if misconfigured. > > **Overview** > Cuts the `9.28.0` release by removing `-SNAPSHOT` across version sources (`.version`, `gradle.properties`, `Config.frameworkVersion`) and updating sample/test-app dependency pins to `9.28.0`. > > Updates release documentation: publishes Dokka docs to the `9.28.0` S3 path, updates `docs/index.html` redirect to `9.28.0`, and rolls `CHANGELOG.latest.md` into a new `9.28.0` section in `CHANGELOG.md`. > > Tweaks release tooling/CI: pins `fastlane-plugin-revenuecat_internal` to a specific git ref (and bumps a few Ruby deps), switches the CircleCI `revenuecat/sdks-common-config` orb to a dev commit, and adds a temporary `test_merge_queue` workflow to exercise `revenuecat/merge-release-pr` with `use_merge_queue: true`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5050888. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
2 tasks
MonikaMateska
pushed a commit
that referenced
this pull request
Apr 20, 2026
… runtime crashes (#3367) <!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> ### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation <!-- Why is this change required? What problem does it solve? --> <!-- Please link to issues following this format: Resolves #999999 --> This PR hardens `showInAppMessagesIfNeeded` against a remaining Play Billing crash path. Resolves #3273, which has not been fully solved by a previous [tentative](#3274). ### Description <!-- Describe your changes in detail --> <!-- Please describe in detail how you tested your changes --> Even after lifecycle/window attachment checks, `BillingClient.showInAppMessages(...)` can still throw a `RuntimeException` (including `NullPointerException`) due to an internal race in Play Billing. This is a defensive boundary around third-party BillingClient behavior: it complements previous activity/window checks by handling exceptions that can still occur between pre-checks and BillingClient’s internal view/token access. Here's exactly what changed: - Wrapped the `showInAppMessages(...)` invocation in `BillingWrapper` with a try/catch - On exception, log the error and skip showing the in-app message instead of crashing the app - Added new log string: BILLING_INAPP_MESSAGE_SHOW_EXCEPTION - Added a regression unit test that simulates `showInAppMessages(...)` throwing a `NullPointerException` and verifies that there are no crash and that the error is logged <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk defensive change that only adds exception handling and logging around a third-party call; behavior changes only when Play Billing throws unexpectedly. > > **Overview** > Prevents a remaining Play Billing crash path by wrapping `BillingClient.showInAppMessages(...)` in `BillingWrapper.showInAppMessagesIfNeeded` with a `try/catch` and logging an error instead of crashing. > > Adds a new log string (`BILLING_INAPP_MESSAGE_SHOW_EXCEPTION`) and a regression unit test that simulates `showInAppMessages` throwing (e.g., `NullPointerException`) and asserts it is logged and does not crash. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5e8afd5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
4 tasks
github-merge-queue Bot
pushed a commit
that referenced
this pull request
Apr 20, 2026
… runtime crashes (#3367) by @matteinn (#3368) <!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> ### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation <!-- Why is this change required? What problem does it solve? --> <!-- Please link to issues following this format: Resolves #999999 --> This PR hardens `showInAppMessagesIfNeeded` against a remaining Play Billing crash path. Resolves #3273, which has not been fully solved by a previous [tentative](#3274). ### Description <!-- Describe your changes in detail --> <!-- Please describe in detail how you tested your changes --> Even after lifecycle/window attachment checks, `BillingClient.showInAppMessages(...)` can still throw a `RuntimeException` (including `NullPointerException`) due to an internal race in Play Billing. This is a defensive boundary around third-party BillingClient behavior: it complements previous activity/window checks by handling exceptions that can still occur between pre-checks and BillingClient’s internal view/token access. Here's exactly what changed: - Wrapped the `showInAppMessages(...)` invocation in `BillingWrapper` with a try/catch - On exception, log the error and skip showing the in-app message instead of crashing the app - Added new log string: BILLING_INAPP_MESSAGE_SHOW_EXCEPTION - Added a regression unit test that simulates `showInAppMessages(...)` throwing a `NullPointerException` and verifies that there are no crash and that the error is logged <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small defensive change limited to in-app message display: it only adds exception handling and logging, plus a unit test, with minimal behavior impact beyond avoiding a crash. > > **Overview** > Prevents app crashes when Google Play Billing’s `BillingClient.showInAppMessages` throws a `RuntimeException` despite lifecycle/window checks, by wrapping the call in a `try/catch` and logging a new `BILLING_INAPP_MESSAGE_SHOW_EXCEPTION` error instead of propagating the crash. > > Adds a regression test that forces `showInAppMessages` to throw (e.g., `NullPointerException`) and asserts the wrapper logs the error and continues without crashing. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit fc5cd08. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> ### Checklist - [ ] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation <!-- Why is this change required? What problem does it solve? --> <!-- Please link to issues following this format: Resolves #999999 --> ### Description <!-- Describe your changes in detail --> <!-- Please describe in detail how you tested your changes --> --------- Co-authored-by: Matteo Innocenti <matteo@appstyx.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
purchases-iosand hybridsMotivation
This PR adds an additional safety check in BillingWrapper.showInAppMessagesIfNeeded to ensure the activity is fully attached to a window before attempting to show Google Play in-app messages, preventing crashes.
Resolves #3273.
Description
While
isFinishingandisDestroyedare already checked,NullPointerExceptioncrashes can still happen while accessing a window token from a null or detached view.Using
peekDecorView().windowTokensafely ensures the activity has a decor view and is attached without accidentally triggering view creation.Note
Low Risk
Low risk: adds an extra null/attachment guard before calling Google Play in-app messaging, reducing crash risk with minimal behavior change (messages may be skipped in more edge cases).
Overview
Prevents potential crashes when showing Google Play in-app messages by adding a new guard in
BillingWrapper.showInAppMessagesIfNeededto ensure theActivityis actually attached to a window (window.peekDecorView().windowTokenpresent) before callingshowInAppMessages.Updates tests to use a helper for an attached
Activityand adds coverage for the new early-return cases whenwindow, decor view, orwindowTokenis missing.Written by Cursor Bugbot for commit af9df05. This will update automatically on new commits. Configure here.