Skip to content

fix(in_app_messaging): re-add Android event listeners after pause and report unheard display messages - #18842

Draft
Lyokone wants to merge 3 commits into
mainfrom
fix/in-app-messaging-event-delivery
Draft

Lyokone wants to merge 3 commits into
mainfrom
fix/in-app-messaging-event-delivery

Conversation

@Lyokone

@Lyokone Lyokone commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fixes three event bugs in the lifecycle events (#18584) and custom display (#18586) added in 0.10.0.

1. Android: event listeners stop after the first activity pause.
The SDK's default display removes every listener on each activity pause. The plugin added them only once, so after the app went to the background, onMessageClicked, onMessageImpression, onMessageDismissed and onMessageDisplayError stayed silent. Fix: the plugin adds them again when an activity resumes.

2. Messages sent to onMessageDisplay are lost when nothing listens yet.
On iOS, the SDK then waits forever for a click, dismiss or error, and shows no other campaign. Fix: a message is held for the first listener. If nobody listens within 5 seconds, or a newer campaign replaces it:

  • iOS reports a display error, so the SDK moves on;
  • Android just drops it. Reporting it there would mark the campaign as seen and block app-open campaigns for 24 hours.

The docs now say to listen to onMessageDisplay before enabling custom display.

3. Android: turning off custom display when it is already off flickers the default display.
It now does nothing in that case.

Tests

  • Dart (method_channel_firebase_in_app_messaging_test.dart, run as Android and iOS): a message sent before the first listener reaches it; on iOS an unheard or replaced message is reported as a display error; on Android it is dropped without a report.
  • Android JUnit:
    • FirebaseInAppMessagingPluginTest: listenersAreAddedAgainWhenAnActivityResumes fails without fix 1. disablingCustomDisplayThatIsOff_leavesTheDefaultDisplayAlone and onDetachedFromEngine_withCustomDisplayOff_leavesTheDefaultDisplayAlone fail without fix 3.
    • EventListenerRegistrationTest covers when listeners are added and removed.

android_unit_tests.yaml now also runs :firebase_in_app_messaging:testDebugUnitTest.

Related Issues

Follow-up to #18584 and #18586.

Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (melos run analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

  • No, this is not a breaking change.

@gemini-code-assist

Copy link
Copy Markdown
Contributor
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

… report unheard display messages

firebase-inappmessaging-display removes all listeners on every activity
pause, so the lifecycle streams went silent on Android after the app was
backgrounded or a campaign opened another activity. The listeners are now
added again when an activity resumes.

A campaign sent to onMessageDisplay while nothing listened was dropped and
never reported, which on iOS blocks every later campaign. It is now held
for the first listener and reported as a display error if none subscribes
within 5 seconds.
A message that arrives on `onMessageDisplay` while nothing listens is
still held for the first listener for a few seconds. When none arrives:

- iOS reports it as a display error, as before, so the SDK releases its
  display lock and can show the next campaign. `onMessageDisplayError`
  fires for it.
- Android now only drops it. `displayErrorEncountered` stores a campaign
  impression there, and for app open campaigns uses up the one a day app
  open limit, for a message nobody saw. Android has no display lock, so
  the campaign stays eligible and triggers again.

On Android, disabling custom display while it is already off, which
`onDetachedFromEngine` also does, no longer pauses and resumes the
default display on the current activity. That restarted a default
message on screen and dropped the listeners of other engines.

The plugin's SDK calls now go through an internal seam, so JUnit tests
drive its activity lifecycle wiring against a fake `Application`.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant