firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.65k stars 3.96k forks source link

[firebase_messaging]: Lost RemoteMessage data in notification #12885

Closed cogivn closed 2 months ago

cogivn commented 3 months ago

Is there an existing issue for this?

Which plugins are affected?

Messaging

Which platforms are affected?

Android

Description

Hi,

I have identified an issue on the Android platform where getInitialMessage() returns null when a user taps on a notification while the app is in a terminated state.

Reproducing the issue

Steps to Reproduce:

1. Application State: The application can be in either the foreground or background state. 2. Notification Delivery: Send a notification message to the application. 3. Application Termination: Terminate the application (e.g., swipe it away from the recent apps list). 4. Notification Interaction: Tap on the notification to launch the application. 5. Actual Behavior: getInitialMessage() returns null.

Firebase Core version

2.32.0

Flutter Version

3.22.1

Relevant Log Output

2024-06-04 15:54:12.395 25962-25962 FirebaseApp             com.example.flutter.app       I  Device unlocked: initializing all Firebase APIs for app [DEFAULT]
2024-06-04 15:54:12.483 25962-25962 FirebaseSessions        com.example.flutter.app       D  Initializing Firebase Sessions SDK.
2024-06-04 15:54:12.513 25962-25962 FirebaseCrashlytics     com.example.flutter.app       I  Initializing Firebase Crashlytics 18.6.3 for com.example.flutter.app
2024-06-04 15:54:12.567 25962-25962 FirebaseInitProvider    com.example.flutter.app       I  FirebaseApp initialization successful
2024-06-04 15:54:12.700 25962-26005 FA                      com.example.flutter.app       I  App measurement initialized, version: 94007
2024-06-04 15:54:19.343 25962-26012 flutter                 com.example.flutter.app       I  │ [debug] | 15:54:19 343ms | Initial Message=null

Flutter dependencies

Expand Flutter dependencies snippet
```yaml firebase_messaging: ^14.9.4 firebase_core: ^2.32.0 firebase_analytics: ^10.10.7 firebase_crashlytics: ^3.5.7 flutter_local_notifications: ^17.1.2 ```

Additional context and comments

No response

TarekkMA commented 3 months ago

Hi @cogivn ,

Thank you for your submission and for taking the time to provide detailed information about the issue. We will look into it and get back to you

russellwheatley commented 3 months ago

I wasn't able to reproduce. Here is how you can test:

  1. Run app in release i.e. flutter run --release.
  2. Terminate app (it will still be running when in release mode).
  3. Send message (I use nodjs admin SDK. See here)
  4. Open app via notification and print out the message returned from getInitialMessage() .

So I had a print here in firebase_messaging example app:

FirebaseMessaging.instance.getInitialMessage().then(
  (value) => setState(
    () {
      print('${value?.data.toString()}');
      _resolved = true;
      initialMessage = value?.data.toString();
    },
  ),
);

and here are the logs from console:

Flutter run key commands.
h List all available interactive commands.
c Clear the screen
q Quit (terminate the application on the device).
I/flutter (21076): Handling a background message 0:1718036389166773%50d7604150d76041
I/flutter (21076): {foo: bar, float: 12034}
I/flutter (21076): FCM Token: dEUSTNftSGmTqpr2TeKx

I sent this in my nodejs admin script:

admin
  .messaging()
  .send(
    {
      token: androidToken,
      data: {
        foo: 'bar',
        float: '12034'
      },
      notification: {
        title: 'A great title',
        body: 'Great content',
      },
      android: {
        // Required for background/terminated app state messages on Android
        priority: 'high',
      },
      apns: {
        payload: {
          aps: {
            // Required for background/terminated app state messages on iOS
            contentAvailable: true,
          },
        },
      },
    },
  )

you can see the data is:

      data: {
        foo: 'bar',
        float: '12034'
      },
cogivn commented 3 months ago

I wasn't able to reproduce. Here is how you can test:

  1. Run app in release i.e. flutter run --release.
  2. Terminate app (it will still be running when in release mode).
  3. Send message (I use nodjs admin SDK. See here)
  4. Open app via notification and print out the message returned from getInitialMessage() .

So I had a print here in firebase_messaging example app:

FirebaseMessaging.instance.getInitialMessage().then(
  (value) => setState(
    () {
      print('${value?.data.toString()}');
      _resolved = true;
      initialMessage = value?.data.toString();
    },
  ),
);

and here are the logs from console:

Flutter run key commands.
h List all available interactive commands.
c Clear the screen
q Quit (terminate the application on the device).
I/flutter (21076): Handling a background message 0:1718036389166773%50d7604150d76041
I/flutter (21076): {foo: bar, float: 12034}
I/flutter (21076): FCM Token: dEUSTNftSGmTqpr2TeKx

I sent this in my nodejs admin script:

admin
  .messaging()
  .send(
    {
      token: androidToken,
      data: {
        foo: 'bar',
        float: '12034'
      },
      notification: {
        title: 'A great title',
        body: 'Great content',
      },
      android: {
        // Required for background/terminated app state messages on Android
        priority: 'high',
      },
      apns: {
        payload: {
          aps: {
            // Required for background/terminated app state messages on iOS
            contentAvailable: true,
          },
        },
      },
    },
  )

you can see the data is:

      data: {
        foo: 'bar',
        float: '12034'
      },

Hi @russellwheatley,

please swap the step 2 and 3 like this:

  1. Send message when app in foreground(displayed the notification but do not tap into notification)
  2. Kill app (Terminate app)
  3. Tap into notification to launch the app again.
Poloten commented 3 months ago

I get the same bug, FirebaseMessaging.instance.getInitialMessage() return null.

Reprodeced only on ios (test on 16.7.8) If I send 2 notification, and click one of them it's work for first and second notification.

Maybe in documentation lost some information about AppDelegete.swift to configure or smt else ?

russellwheatley commented 3 months ago

Hey @cogivn - I was able to reproduce, I'll see what can be done to fix this issue 👍

russellwheatley commented 3 months ago

hmmmm, after investigating for some time, I don't think there is anything we can do about this. The problem is; we receive the RemoteMessage here, but when the user taps the notification, we receive the intent here.

The intent contains the following in the extras:

{
    notificationId: 123456,
    payload: ""
}

This does not allow us to tie the message received with the notification tapped (notificationId is not a property on the RemoteMessage when the message is received). This is different to when the message is received in the background. Here is the documentation

This specific part:

Screenshot 2024-06-12 at 12 19 01

The data is not contained within the intent itself when the message is received in the foreground. Therefore, we have no way of knowing what the initial message is.

Your best bet might be to use data-only messages and handle the notifications yourself rather than use firebase messaging to handle the notifications.

cogivn commented 3 months ago

Hi @russellwheatley,

Would be grateful if you could elaborate on the use of data-only messages as a potential solution to this issue. While I understand that notification handling for both notification messages and data-only messages is likely required when app is in foreground on the Android platform, the problem appears to persist even when a user taps on a notification after the application has been terminated.

russellwheatley commented 3 months ago

@cogivn - I mean you might consider using data-only messages to trigger a notification using another Flutter plugin (such as flutter_local_notifications). Presumably they don't have the same limitation on android when the message is received in the foreground.