Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[firebase_messaging]: getInitialMessage returns null when clicking on the ActionButton if the app is terminated. #17051

Open
5 tasks done
VictorJava opened this issue Feb 4, 2025 · 11 comments
Labels
blocked: customer-response Waiting for customer response, e.g. more information was requested. platform: ios Issues / PRs which are specifically for iOS. plugin: messaging Stale Issue with no recent activity type: bug Something isn't working

Comments

@VictorJava
Copy link

VictorJava commented Feb 4, 2025

Is there an existing issue for this?

  • I have searched the existing issues.

Are you aware of the differences between iOS and Android background message handling?

  • I understand that iOS and Android background messages behave differently, and I've designed my application with that in mind.

Do you have an active Apple Developer account?

  • I have an active Apple Developer account.

Are you using a physical iOS device to test background messages?

  • I am using a physical iOS device to test background messages.

Have you enabled "Remote Notifications" & "Background Mode" (Checking options for "Background Processing" & "Remote Notifications") in your app's Xcode project?

Image

Have you created an APNs key in your Apple Developer account & uploaded this APNs key to your Firebase console?

Image

Have you disabled method swizzling for Firebase in your app?

Image

Are you sending messages to your app from the Firebase Admin SDK?

I am using the Postman to this.
That is my JSON for Postman call. Feel free to check https://stackoverflow.com/a/62670409/21734721 how to grab auth.

{
  "message": {
    "token": "eztm3jfE9UsgrphZUCSSMe:APA91bFj8qulosQh-_4mGlBk-96eWRQ62_kesdSQ0ICGVSKM9ylKVZWBtzhbN5esGMS5cJK3d4epzUDnq_q1CC8HKp3vCUi-faJLIlE7S_5eK4u8HxlDcCs",
    "notification": {
      "title": "some text",
      "body": "some text (optional)",
  },
    "data": {
      "style": "red_high_leak",
      "title": "some text (optional)",
      "message": "some text",
      "bodyAction": "active_leak",
      "contextDataType": "leak",
    },
    "apns": {
       "headers": {
         "apns-priority": "5",
       },
       "payload": {
         "aps": {
           "category": "active_leak",
           "content-available": 1,
           "mutable-content" : 1,
         }
       }
     },
  },
}

Have you requested permission from the user to receive notifications?

  • I have the relevant permission to receive notifications.

Have you used the 'Console' application on your macOS device to check if the iOS device's system is throttling your background messages?

Sorry, I can`t attach the logger to the console.

Additional context and comments

Steps to Reproduce:

  1. I added buttons to a category during app initialization. For example, the active_leak category has two buttons. For my case I use https://pub.dev/packages/flutter_local_notifications
  2. Open the app at least once.
  3. Allow notifications for the app.
  4. Minimize the app and swipe it away (Terminate state – the app is not running in the background or in the list of active apps).
  5. Send a push notification via APNs, where the category matches the one from step 1: "category": "active_leak".
  6. Receive the push notification.
  7. Tap on one of the buttons.
  8. The app opens.
  9. getInitialMessage returns null and even final NotificationAppLaunchDetails? notificationAppLaunchDetails =
    await notificationsPlugin.getNotificationAppLaunchDetails().didNotificationLaunchApp returns false

I understand that iOS(or Firebase service) displays the notification, not flutter_local_notifications.

Keep in mind that getInitialMessage is not null when tapping on the notification body, but if the user taps on a button, getInitialMessage is null, and didNotificationLaunchApp is false. It works fine if notification is received when the app is in a background state, but not in termitated.

However, the app still opens, meaning the click action is registered.
*How can I retrieve the payload of the notification when the user taps a button?

That is how I add the ActionButtons using the flutter_local_notifications library

    DarwinNotificationAction actionIgnoreLeak = DarwinNotificationAction.plain(
      NotificationButtonAction.ignoreLeak.value,
      ignoreStr,
      options: <DarwinNotificationActionOption>{
        DarwinNotificationActionOption.foreground,
      },
    );

    DarwinNotificationAction actionActiveLeak = DarwinNotificationAction.plain(
      NotificationButtonAction.activeLeak.value,
      detailsStr,
      options: <DarwinNotificationActionOption>{
        DarwinNotificationActionOption.foreground,
      },
    );

    DarwinNotificationCategory categoryIgnoreAndDetails =
        DarwinNotificationCategory(
            NotificationBuilder.darwinNotificationCategoryActiveLeak,
            actions: <DarwinNotificationAction>[
          actionIgnoreLeak,
          actionActiveLeak,
        ]);

    initializationSettingsDarwin = DarwinInitializationSettings(
      requestAlertPermission: false,
      requestBadgePermission: false,
      requestSoundPermission: false,
      notificationCategories: <DarwinNotificationCategory>[
        categoryIgnoreAndDetails
      ],
    );
@VictorJava VictorJava added Needs Attention This issue needs maintainer attention. platform: ios Issues / PRs which are specifically for iOS. plugin: messaging type: bug Something isn't working labels Feb 4, 2025
@SelaseKay
Copy link
Contributor

SelaseKay commented Feb 4, 2025

Hi @VictorJava, thanks for the detailed report. This is the intended behaviour of getInitialMessage as described in the documentation. It returns the payload only when the actual notification is pressed, otherwise, it's null.

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 4, 2025
@VictorJava
Copy link
Author

@SelaseKay Thank you for your response. Of course, I have read the documentation. How can I retrieve the payload when a button is pressed? The button has the parameter UNNotificationActionOptions.foreground. Could you please take a look https://developer.apple.com/documentation/usernotifications/unnotificationactionoptions/foreground This means that the system does not handle the button press itself but instead opens the application, even if it was previously terminated.

It is expected that after this, I should receive the payload, isn't that right? After all, this is the standard iOS logic. Are you saying that the firebase_messaging package does not cover the full functionality of the iOS system?

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Feb 5, 2025
@SelaseKay
Copy link
Contributor

Hi @VictorJava, are you using silent push notifications and relying on flutter_local_notifications to handle their display?

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 5, 2025
@VictorJava
Copy link
Author

VictorJava commented Feb 6, 2025

@SelaseKay Thanks for your reply. No, for iOS, I use https://pub.dev/packages/flutter_local_notifications only to add a category with buttons during app initialization: "category": "active_leak". I didn`t find how I can add categories and actions with https://pub.dev/packages/firebase_messaging. Maybe, you know how to do it without flutter_local_notifications? Then, I send an FCM JSON payload that includes a notification and the category.

{
  "message": {
    "token": "c1z84o8t-k-zv6Sj2vSnvP:APA91bGLKTEXiaIE6J5vXt76UqeCRVKzbQiT6AL4UpYY036yhM6fcXycW7lZMSSwQpwZH3iFUzjSDzm5Wh4gF5ZWvfgldG7rgJZJXUq-P4gKHJQWP01atwM",
      "notification": {
    "title": "Hello!2",
    "body": "This is a push notification.",
  },
    "data": {
      "style": "red_low_leak",
      "title": "some text (optional)",
      "message": "some text",
      "bodyAction": "active_leak",
      "buttons": "{ \"positive\": { \"type\": \"details\", \"action\": \"active_leak\", \"showInSystemTray\": true }, \"negative\": { \"type\": \"ignore_leak\", \"showInSystemTray\": true, \"action\": \"ignore_leak\" } }",
      "contextDataType": "leak",
      "contextData": "{\"eventId\": 123}",
    },
    "apns": {
       "headers": {
         "apns-priority": "5",
       },
       "payload": {
         "aps": {
           "category": "active_leak",
           "content-available": 1,
           "mutable-content" : 1,
           "sound" : "default",
         }
       }
     },
  },
}

If the app is in a terminated state, iOS natively triggers the notification with the pre-defined category "category": "active_leak". The iOS system handles this automatically, without the app's involvement. As I understand, this is standard iOS functionality.

Please refer to the official documentation: Declaring Your Actionable Notification Types.

If you tap on the message body while the app is in a terminated state, getInitialMessage returns the data.
However, if you tap on a button instead of the message body while the app is in a terminated state, getInitialMessage returns null. How I can in this case receive the non null data?

Thanks for your help.

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Feb 6, 2025
@VictorJava
Copy link
Author

Can someone help me figure out how to get the notification payload when opening the app (by clicking on the notification) if the notification was displayed while the app was terminated?

@SelaseKay
Copy link
Contributor

Hi @VictorJava, could you please create a minimal repository that reproduces the issue and share the link here?

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 10, 2025
@VictorJava
Copy link
Author

@SelaseKay Thanks for your reply. To send push notifications to iOS, you will need my APNs key, Apple ID team, bundle ID, and access to the FCM project. For obvious reasons, I can’t share these details publicly.

If I prepare the code without the APNs key, Apple ID team, bundle ID, and FCM project access, along with detailed steps on how to integrate it, would you just need to connect the code to FCM on your end?

Would that be sufficient for you?

@VictorJava
Copy link
Author

@SelaseKay Thanks for your reply. To send push notifications to iOS, you will need my APNs key, Apple ID team, bundle ID, and access to the FCM project. For obvious reasons, I can’t share these details publicly.

If I prepare the code without the APNs key, Apple ID team, bundle ID, and FCM project access, along with detailed steps on how to integrate it, would you just need to connect the code to FCM on your end?

Would that be sufficient for you?

@SelaseKay Just a gentle reminder.

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Feb 18, 2025
@SelaseKay
Copy link
Contributor

Hi @VictorJava, you can provide the sample without those sensitive details.

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 18, 2025
@VictorJava
Copy link
Author

@SelaseKay I managed to intercept notification button presses using native Swift, which sends callbacks to Flutter. Unfortunately, getInitialMessage still didn't work, even with version 15.2.2. I'll talk to my customers if they allocate some time for me, I'll create a dummy application for you.
native AppDelegate.swift class

import UIKit
import Flutter
import Firebase
import UserNotifications

@main
@objc class AppDelegate: FlutterAppDelegate, MessagingDelegate {
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        FirebaseApp.configure()
        
        // Setting up Firebase Messaging
        Messaging.messaging().delegate = self
        UNUserNotificationCenter.current().delegate = self
        
        // register remote messages
        application.registerForRemoteNotifications()
        
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    
    // handle notification clicks (action button or notification body)
    override func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    ) {
        let userInfo = response.notification.request.content.userInfo
        
        // check if an action was clicked (action button)
        if response.actionIdentifier == UNNotificationDefaultActionIdentifier {
            // notification body click
            self.sendClickNotificationToFlutter(userInfo)
        } else {
            // notification button click (action button)
            var userInfoWithAction = userInfo
            userInfoWithAction["actionIdentifier"] = response.actionIdentifier
            self.sendClickNotificationToFlutter(userInfoWithAction)
        }
        
        completionHandler()
    }
    
    // push data to Flutter
    func sendClickNotificationToFlutter(_ userInfo: [AnyHashable: Any]) {
        if let controller = window?.rootViewController as? FlutterViewController {
            let channel = FlutterMethodChannel(name: "app/launchNotification", binaryMessenger: controller.binaryMessenger)
            channel.invokeMethod("onNotificationClick", arguments: userInfo)
        }
    }
    
    // register FCM token
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("Firebase registration token: \(String(describing: fcmToken))")
    }
}

@google-oss-bot google-oss-bot removed the blocked: customer-response Waiting for customer response, e.g. more information was requested. label Feb 18, 2025
@google-oss-bot google-oss-bot added the Needs Attention This issue needs maintainer attention. label Feb 18, 2025
@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 24, 2025
@google-oss-bot google-oss-bot added the Stale Issue with no recent activity label Feb 27, 2025
@google-oss-bot
Copy link

Hey @VictorJava. 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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked: customer-response Waiting for customer response, e.g. more information was requested. platform: ios Issues / PRs which are specifically for iOS. plugin: messaging Stale Issue with no recent activity type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants