Flutter In-App Messages Lifecycle Callbacks

In-App Messages

Lifecycle Callbacks

Subscribe to Reteno.onInAppMessageStatusChanged to observe:

  • InAppShouldBeDisplayed before display;
  • InAppIsDisplayed after display;
  • InAppShouldBeClosed before close;
  • InAppIsClosed after close;
  • InAppReceivedError when display fails.
Reteno.onInAppMessageStatusChanged.listen((status) {
  switch (status) {
    case InAppShouldBeDisplayed():
      print('In-app should be displayed');
    case InAppIsDisplayed():
      print('In-app is displayed');
    case InAppShouldBeClosed(:final action):
      print('In-app should be closed: $action');
    case InAppIsClosed(:final action):
      print('In-app is closed: $action');
    case InAppReceivedError(:final errorMessage):
      print('In-app error: $errorMessage');
  }
});

Close statuses contain an InAppMessageAction with three booleans — isCloseButtonClicked, isButtonClicked, and isOpenUrlClicked — that indicate whether the user selected the close button, an action button, or a URL. All three are false for a generic Android dismiss. The status models do not expose message ID, interaction ID, or display source.

Pause and Resume In-App Messages

Pause in-app messages during critical flows such as registration or payment, then resume them when the flow finishes:

await Reteno().pauseInAppMessages(true);  // Pause.
await Reteno().pauseInAppMessages(false); // Resume.

Resuming displays at most the first postponed message and clears the rest of the queue. Do not rely on every skipped message being replayed.

To start the SDK in a paused state, set the initialization option:

await Reteno().initialize(
  accessKey: '<your_access_key>',
  options: const RetenoInitOptions(
    isPausedInAppMessages: true,
  ),
);

Android In-App Custom Data

Reteno.onRetenoInAppCustomDataReceived carries custom data from a push-triggered in-app message. The stream is Android-only; the iOS bridge does not emit it.

Reteno.onRetenoInAppCustomDataReceived.listen((event) {
  print('In-app ID: ${event.inAppId}');
  print('Source: ${event.source}');
  print('URL: ${event.url}');
  print('Data: ${event.data}');
});

The event is a RetenoInAppCustomData:

class RetenoInAppCustomData {
  final String? url;
  final String source;
  final String inAppId;
  final Map<String, String> data;
}