flutterfire icon indicating copy to clipboard operation
flutterfire copied to clipboard

[firebase_messaging]: FirebaseMessaging.instance.getInitialMessage() is always null on iOS after upgrade to 15.2.2

Open lukyanov opened this issue 9 months ago • 22 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues.

Which plugins are affected?

Messaging

Which platforms are affected?

iOS

Description

await FirebaseMessaging.instance.getInitialMessage() is always null when the app is opened from the "killed" state.

The plugin version 15.1.6 (the previous version I used) worked as expected.

iOS 18.3.1

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage()
  // initialMessage is always null here
}

void main() async {
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  ...
}

Reproducing the issue

  1. Close the app (swipe it away)
  2. Send a notification via firebase console or with a script (in my case I have a link attached to the notification data)
  3. Tap the notification
  4. Observe initialMessage being null

Firebase Core version

3.11.0

Flutter Version

3.27.2

Relevant Log Output


Flutter dependencies

No response

Additional context and comments

No response

lukyanov avatar Feb 17 '25 15:02 lukyanov

Hi @lukyanov, I've been able to reproduce this issue with the firebase_messaging example app. As a workaround, add a delay of 3 seconds before calling getInitialMessage and see if it resolves your issue.

SelaseKay avatar Feb 17 '25 15:02 SelaseKay

Hey @lukyanov. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar Feb 26 '25 02:02 google-oss-bot

A portion of users of my app on android have been hitting this issue suddenly over the past few weeks. Not sure if there was an android update that broke it, but for the affected users now every RemoteMessage ends up filled with null values.

austinwitherspoon avatar Mar 01 '25 17:03 austinwitherspoon

I observe a similar issue on Android, will this issue be resolved?

fahmisdk6 avatar Mar 10 '25 02:03 fahmisdk6

I’m not sure if this will be a hint, but when the RemoteMessage of getInitialMessage() is null, onMessage.listen does not work in the foreground state. However, when the RemoteMessage of getInitialMessage() is not null, onMessage.listen works in the foreground state.

The test was conducted on the Galaxy S25 Ultra, and normal operation was confirmed on the Galaxy Note 10 Plus and Galaxy S22.

Kamuel09 avatar Mar 13 '25 07:03 Kamuel09

facing same issue

pranil-key avatar Mar 17 '25 04:03 pranil-key

I am facing an issue where FirebaseMessaging.onMessage does not trigger on some real Android devices when using Firebase HTTP v1, but it works fine on the Android Emulator. Additionally, getInitialMessage always returns null when opening the app from a notification click. However, when using Firebase Console to send notifications, both functions work correctly on all devices. Strangely, even when onMessage is not triggered, a notification popup still appears, which should not happen since I handle notifications manually. This issue seems to occur only on some real Android devices, and I would appreciate any insights or solutions.

bunpotks avatar Mar 18 '25 02:03 bunpotks

Hey @lukyanov. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar Mar 27 '25 01:03 google-oss-bot

Even though I didn't change anything, getInitialMessage() started receiving non-null values for remoteMessage. Was there any modification made by any chance???

Kamuel09 avatar Mar 27 '25 01:03 Kamuel09

Even though I didn't change anything, getInitialMessage() started receiving non-null values for remoteMessage. Was there any modification made by any chance???

In my case this behaviour is happening randomly. few times I'm getting data in getInitialMessage() method but few time the value is being null.

pranil-key avatar Mar 27 '25 07:03 pranil-key

Hey @lukyanov. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar Apr 07 '25 01:04 google-oss-bot

Even though I didn't change anything, getInitialMessage() started receiving non-null values for remoteMessage. Was there any modification made by any chance???

In my case this behaviour is happening randomly. few times I'm getting data in getInitialMessage() method but few time the value is being null.

any update ?

pranil-key avatar Apr 07 '25 12:04 pranil-key

Not sure why I'm being asked for updates. I thought I gave everything. @SelaseKay successfully reproduced the issue, so I didn't expect I needed to provide anything else.

lukyanov avatar Apr 07 '25 14:04 lukyanov

Given a workaround of adding a delay works makes me think it is just a thread issue. Could you try using a .then callback and letting me know how it goes?

FirebaseMessaging.instance.getInitialMessage().then((message) {
  print('Initial message: $message');
});

MichaelVerdon avatar Apr 10 '25 10:04 MichaelVerdon

Given a workaround of adding a delay works makes me think it is just a thread issue. Could you try using a .then callback and letting me know how it goes?

FirebaseMessaging.instance.getInitialMessage().then((message) {
  print('Initial message: $message');
});

it's not working either for me

pranil-key avatar Apr 15 '25 14:04 pranil-key

Hi guys! Any update on this? I'm still on version 15.1.6 to avoid this issue.

lukyanov avatar Apr 23 '25 07:04 lukyanov

I got the same issue, but I fixed it.

On Android, everything works perfectly. However, on iOS, it doesn't work as expected.

I resolved this by creating a custom Flutter plugin and communicating with native iOS code to handle notifications.

Reference Documents: Handling incoming push notifications in the background: [UIApplicationDelegate - application(:didReceiveRemoteNotification:fetchCompletionHandler:)](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/application(:didreceiveremotenotification:fetchcompletionhandler/)

Handling user interactions with notification actions: [UNUserNotificationCenterDelegate - userNotificationCenter(:willPresent:withCompletionHandler:)](https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate/usernotificationcenter(:willpresent:withcompletionhandler/)

Declaring notification actions (e.g., Accept, Decline buttons): Declaring Your Actionable Notification Types

*My Approach:

  • When a notification is sent from the server, the didReceiveRemoteNotification method receives the notification data from APNs.

  • I then use that data to create a local notification on iOS.

  • Next, I use willPresent to listen for user interactions with the notification actions.

  • Once an interaction occurs, I send the notification details back to Flutter via eventSink.

✅ This approach works even when the app has been terminated.

This is where I declared the getinitialMessage(): Image

This is where I declared my plugin: Image

Let's see the results printed when I tap in the notice when the app is in Terminated Image

Hope this helps you <3 <3

lirunghi261 avatar May 09 '25 07:05 lirunghi261

Hey there @lukyanov does @lirunghi261 solution work for you?

MichaelVerdon avatar May 23 '25 12:05 MichaelVerdon

Hey there @lukyanov does @lirunghi261 solution work for you?

Well, maybe, I don't know. My initial issue was about the official firebase messaging plugin, not about custom workarounds. So I'm not sure I understand the question. Shouldn't the solution be a part of the plugin itself? Will you just close the issue if the custom workaround works? I'm a bit surprised to be honest.

lukyanov avatar Jun 03 '25 06:06 lukyanov

It's been more than 3 months from the upgrade (from 15.1.6 to 15.2.2) that broke the behaviour the plugin officially states in its documentation.

lukyanov avatar Jun 03 '25 06:06 lukyanov

Hi @lukyanov, you mentioned that it works fine on version 15.1.6, but I'm still able to reproduce the issue on that version. Could you confirm if that version still working as expected for you?

SelaseKay avatar Jun 12 '25 14:06 SelaseKay

It's been more than 3 months from the upgrade (from 15.1.6 to 15.2.2) that broke the behaviour the plugin officially states in its documentation.

I cannot even use version 15.1.6 as a temporary workaround because of this issue: https://github.com/firebase/flutterfire/issues/16670

May I ask your firebase_core and firebase_messaging versions?

WillowWisp avatar Jun 13 '25 11:06 WillowWisp

I experienced the same issue, any update? firebase_messaging: ^15.1.6 firebase_core: ^3.12.1

newengine avatar Jun 24 '25 18:06 newengine

Hi @lukyanov - I have had a look into this issue. I'm a bit confused really, the code snippet you provided:

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage()
  // initialMessage is always null here
}

does indeed return a null initialMessage, but I would expect it to because the background message handler fires largely before the user has a chance to tap the notification and open the app from a terminated state.

However, if I open the app with a notification, and then attempt to retrieve the initialMessage via this button: https://github.com/firebase/flutterfire/blob/main/packages/firebase_messaging/firebase_messaging/example/lib/main.dart#L327

I can retrieve the initialMessage without issue.

I am aware of another issue that might occur; I believe this AppDelegate call handler which retrieves initial message: https://github.com/firebase/flutterfire/blob/main/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m#L214

Might not have been called before there is a chance to get the initial message via getInitialMessage() which is why a delay has been suggested to be 100% sure it has fired.

I took a look at the code diff between latest version and the last version you suggested getInitialMessage() was working for iOS plugin code: https://github.com/firebase/flutterfire/blob/main/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m

This is the only PR I could find that changes that file: https://github.com/firebase/flutterfire/pull/13484/files

I don't think this should effect the handling of initial messages.

russellwheatley avatar Jul 17 '25 08:07 russellwheatley

We are suffering from the same issue. Android works fine but a delay for iOS is required. We tried to downgrade to 15.1.6 as well but that didn't seem to fix the issue for iOS. Only a delay worked.

PeterLeconte avatar Aug 14 '25 15:08 PeterLeconte

Hi,

Suffering from the same issue as well in version 15.1.6, on iOS only.

It seems to me this problem is older, because in those issues I think the problem was the same :

  • https://github.com/firebase/flutterfire/issues/12958 (version reported : 14.9.4)
  • https://github.com/firebase/flutterfire/issues/12453#event-15798546479 (version reported : 15.1.5)

I can confirm the 2 seconds delay seems to be working, but if possible we would rather avoid adding this artifical delay (it's not a very good user experience)

tof43 avatar Aug 19 '25 16:08 tof43

I can confirm the 2 seconds delay seems to be working, but if possible we would rather avoid adding this artifical delay (it's not a very good user experience)

We also tried 2 seconds but is not consistent in our case. I recommend putting it even higher if you can get away with it... It's an enormous delay too for something like this. I would've expected that to be more than enough.

PeterLeconte avatar Aug 20 '25 11:08 PeterLeconte

I have the same issue in my app.

my config:

flutter: 3.24.3
firebase_core: ^4.1.0
firebase_messaging: ^16.0.1
platform: iOS

FirebaseMessaging.instance.getInitialMessage().then((message){ }) message is always null.. how to fix it ?

suzyvivi avatar Sep 02 '25 13:09 suzyvivi

I have the same issue in my app.

my config:

flutter: 3.24.3
firebase_core: ^4.1.0
firebase_messaging: ^16.0.1
platform: iOS

FirebaseMessaging.instance.getInitialMessage().then((message){ }) message is always null.. how to fix it ?

I tried the commonly mentioned approach of triggering getInitialMessage via delay, but it didn’t work.

So I checked the source code of firebase_messaging, and found the following explanation:

/// If the application has been opened from a terminated state via a [RemoteMessage]
  /// (containing a [Notification]), it will be returned, otherwise it will be `null`.
  ///
  /// Once the [RemoteMessage] has been consumed, it will be removed and further
  /// calls to [getInitialMessage] will be `null`.
  ///
  /// This should be used to determine whether specific notification interaction
  /// should open the app with a specific purpose (e.g. opening a chat message,
  /// specific screen etc).
  ///
  /// on Android, if the message was received in the foreground, and the notification was
  /// pressed whilst the app is in a background/terminated state, this will return `null`.
  Future<RemoteMessage?> getInitialMessage() {
    return _delegate.getInitialMessage();
  }

Since I can see the notification banner in the system, the Notification cannot be null. So it should be the second case: Once the [RemoteMessage] has been consumed, it will be removed and further calls to [getInitialMessage] will be null.

Following this line of thought, I continued to look into the plugin’s source code. The specific path is /firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m

Around line 1054, there is this piece of code:

- (nullable NSDictionary *)copyInitialNotification {
  @synchronized(self) {
    // Only return if initial notification was sent when app is terminated. Also ensure that
    // it was the initial notification that was tapped to open the app.
      
    if (_initialNotification != nil && [_initialNotificationID isEqualToString:_notificationOpenedAppID]) {
        NSDictionary *initialNotificationCopy = [_initialNotification copy];
        _initialNotification = nil;
       return initialNotificationCopy;
    } 
  }

  return nil;
}

I set a breakpoint and debugged it, and found that the code never entered the if block. _notificationOpenedAppID was null, so it could not be equal to _initialNotificationID. At that moment, _initialNotificationID did hold the initial message.

Also, _initialNotification = nil; sometimes gets triggered too early. When remoteMessage is assigned to _initialNotification, it is cleared beforehand. This seems like a timing issue.

- (nullable NSDictionary *)copyInitialNotification {
  @synchronized(self) {
    // Only return if initial notification was sent when app is terminated. Also ensure that
    // it was the initial notification that was tapped to open the app.
      
    if (_initialNotification != nil ) {
        NSDictionary *initialNotificationCopy = [_initialNotification copy];
        //_initialNotification = nil;
       return initialNotificationCopy;
    } 
  }

  return nil;
}

For now, I temporarily modified the code like this. I found that in Flutter, getInitialMessage() then returns as expected.

I did a quick test, and so far it doesn’t affect other business callbacks. Note: this is not the optimal solution, just a temporary workaround.

Hopefully the official team can address this issue fundamentally.

suzyvivi avatar Sep 05 '25 07:09 suzyvivi

Not working for me :/ @suzyvivi

yusufnadar avatar Sep 12 '25 08:09 yusufnadar