Problem
When the user taps an FCM notification while the app process is killed, our launcher Activity starts with push data in Intent.extras, but NotifierManager.Listener.onNotificationClicked is often not called because we register listeners in Compose (LaunchedEffect) after MainActivity.onCreate().
In NotifierManagerImpl.onNotificationClicked, if listeners.isEmpty() the event is only logged and dropped — there is no pending/buffered payload API.
Legacy behavior (previous native WebView app)
We detected a notification launch in Activity.onCreate with:
intent.getStringExtra("google.message_id") != null
Then we read FCM data keys: msg.id, msg.title, msg.body, msg.user, persisted the message, and navigated to our messages screen (initialRoute).
Current KMPNotifier behavior (observed)
NotifierManager.onCreateOrOnNewIntent(intent) must be called in launcher Activity onCreate / onNewIntent — we do this.
- Click detection uses
ACTION_NOTIFICATION_CLICK or google.sent_time (KEY_ANDROID_FIREBASE_NOTIFICATION), not google.message_id.
AndroidNotifier.getPendingIntent() sets ACTION_NOTIFICATION_CLICK and copies payloadData into extras; launch intent is PackageManager.getLaunchIntentForPackage().
- System-shown FCM tray notifications (app killed) often deliver Firebase extras including
google.message_id, which our legacy app relied on.
- The library does not open any screen — only callbacks. That is fine; we need a reliable click payload on cold start.
Expected / requested changes
1. Explicit launch marker on all notification PendingIntents
Add a documented extra on every notification PendingIntent from the library, e.g.:
const val EXTRA_NOTIFICATION_LAUNCH = "com.mmk.kmpnotifier.EXTRA_NOTIFICATION_LAUNCH"
// intent.putExtra(EXTRA_NOTIFICATION_LAUNCH, true)
Use it in isNotificationClicked together with existing markers.
2. Treat google.message_id as a notification-click marker
In NotifierManager.onCreateOrOnNewIntent, include Firebase’s google.message_id in click detection (in addition to ACTION_NOTIFICATION_CLICK and google.sent_time), for compatibility with default FCM tray notifications and legacy apps.
3. Buffer notification-click payload until first listener is registered
Example API:
// NotifierManagerImpl
private var pendingNotificationClick: PayloadData? = null
fun onNotificationClicked(data: PayloadData) {
if (listeners.isEmpty()) pendingNotificationClick = data
else listeners.forEach { it.onNotificationClicked(data) }
}
// NotifierManager (public)
fun consumePendingNotificationClick(): PayloadData? =
pendingNotificationClick.also { pendingNotificationClick = null }
Or deliver the pending click automatically on addListener / setListener.
This helps KMP/Compose apps that cannot register listeners before Activity.onCreate finishes, even if the README recommends registering in Application.onCreate (see also #74).
4. Documentation
- Document which Intent extras indicate “opened from notification” (
EXTRA_NOTIFICATION_LAUNCH, ACTION_NOTIFICATION_CLICK, google.message_id, google.sent_time).
- Clarify that business keys (
msg.id, etc.) are passed through in PayloadData unchanged.
- Note cold start:
onCreate + notification extras vs warm start: onNewIntent.
What we will do on our side
We will move NotifierManager.addListener to Application.onCreate (as recommended). Items (2) and (3) would still improve FCM tray compatibility and cold start for Compose/KMP consumers.
Thank you!
Problem
When the user taps an FCM notification while the app process is killed, our launcher Activity starts with push data in
Intent.extras, butNotifierManager.Listener.onNotificationClickedis often not called because we register listeners in Compose (LaunchedEffect) afterMainActivity.onCreate().In
NotifierManagerImpl.onNotificationClicked, iflisteners.isEmpty()the event is only logged and dropped — there is no pending/buffered payload API.Legacy behavior (previous native WebView app)
We detected a notification launch in
Activity.onCreatewith:Then we read FCM data keys:
msg.id,msg.title,msg.body,msg.user, persisted the message, and navigated to our messages screen (initialRoute).Current KMPNotifier behavior (observed)
NotifierManager.onCreateOrOnNewIntent(intent)must be called in launcher ActivityonCreate/onNewIntent— we do this.ACTION_NOTIFICATION_CLICKorgoogle.sent_time(KEY_ANDROID_FIREBASE_NOTIFICATION), notgoogle.message_id.AndroidNotifier.getPendingIntent()setsACTION_NOTIFICATION_CLICKand copiespayloadDatainto extras; launch intent isPackageManager.getLaunchIntentForPackage().google.message_id, which our legacy app relied on.Expected / requested changes
1. Explicit launch marker on all notification PendingIntents
Add a documented extra on every notification
PendingIntentfrom the library, e.g.:Use it in
isNotificationClickedtogether with existing markers.2. Treat
google.message_idas a notification-click markerIn
NotifierManager.onCreateOrOnNewIntent, include Firebase’sgoogle.message_idin click detection (in addition toACTION_NOTIFICATION_CLICKandgoogle.sent_time), for compatibility with default FCM tray notifications and legacy apps.3. Buffer notification-click payload until first listener is registered
Example API:
Or deliver the pending click automatically on
addListener/setListener.This helps KMP/Compose apps that cannot register listeners before
Activity.onCreatefinishes, even if the README recommends registering inApplication.onCreate(see also #74).4. Documentation
EXTRA_NOTIFICATION_LAUNCH,ACTION_NOTIFICATION_CLICK,google.message_id,google.sent_time).msg.id, etc.) are passed through inPayloadDataunchanged.onCreate+ notification extras vs warm start:onNewIntent.What we will do on our side
We will move
NotifierManager.addListenertoApplication.onCreate(as recommended). Items (2) and (3) would still improve FCM tray compatibility and cold start for Compose/KMP consumers.Thank you!