skip to Main Content

I know this has been asked before, but this query is slightly different.

I am sending a push notification to an iOS Flutter app. Foreground handling works correctly. Background/killed mode works in that a notification message appears in the system tray and if the user clicks on that message is opens the app and the message details are sent through.

However if I put the app in the background, send a message, I DON’T click on the system tray notification but instead just bring the app back to the foreground, I can see the background handler/listener hasn’t done anything. So if the user (ahem, client) has the app in the background and ignores the system tray notification, brings the app to the foreground themselves, no message data is received.

Additionally, inclusion of an image is also being totally ignored.

The xCode capabilities include Background Modes (Background fetch and Remote notifications), and Push Notifications.

My payload looks like this:

"message": {
    "token": "my-token-here",        
    "data": {
        "data_value_1": "DATA VALUE 1 test",
    },
    "notification": {
        "title": "NOTIFICATION Title",
        "body": "NOTIFICATION Body",
    },
    "apns":{
      "payload":{
         "aps":{
            "mutable-content": 1,                 
            "content_available": 1, 
         }
      }, 
      "headers": {
       "apns-priority": "10",
      },
      "fcm_options": {
         "image": 'https://t4.ftcdn.net/jpg/01/43/42/83/240_F_143428338_gcxw3Jcd0tJpkvvb53pfEztwtU9sxsgT.jpg'
      }
      }

      }

In addition to the FirebaseMessaging.onMessageOpenedApp.listen and FirebaseMessaging.onMessage.listen handling (which both work), I include this in my main.dart file, which doesn’ seem to be working:

void main() async{
WidgetsBinding widgetsBinding = WidgetsFlufluttertterBinding.ensureInitialized();

  ...
  ...  
@pragma('vm:entry-point') 
Future<void>firebaseMessagingBackgroundHandler(RemoteMessage message) async { 
    print('listener hit (background)...message is received!!!!!!!!!!'); 
    //THE ABOVE NEVER TRIGGERS!; 
} 
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); 
await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform );    
runApp(MyApp()); 
}

I’ve checked all the documents on Firebase and similar posts but I can’t get it working…

According to https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages:

When in the BACKGROUND, apps receive the notification payload in the notification tray, and ONLY handle the data payload when the user taps on the notification.

This says to me that placing an app from the background to the foreground without pressing the notification that comes through system tray, will ignore the message entirely. So the question is, why then does "firebaseMassagingBackgroundHandler" exist? Is this just for Android?

2

Answers


  1. main.dart file

    @pragma('vm:entry-point')
    Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
    }
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
      FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
    
      runApp(child: MyApp());
    }
    
    1. Add the following lines to the application method in the AppDelegate.m/AppDelegate.swift file of your iOS project.

    Objective-C:

    if (@available(iOS 10.0, *)) {
      [UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
    }
    

    Swift:

    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
    

    2.AppDelegate.swift

    import UIKit
    import Flutter
    

    import flutter_local_notifications // add this line

    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
     
          FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
            GeneratedPluginRegistrant.register(with: registry)
        }
    
        if #available(iOS 10.0, *) {
          UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
        } 
    

    // add this line

        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }
    

    ios notification permission

    await _flutterLocalNotificationsPlugin
              .resolvePlatformSpecificImplementation<
                  IOSFlutterLocalNotificationsPlugin>()
              ?.requestPermissions(
                alert: true,
                badge: true,
                sound: true,
              );
    

    All of this checks the working iOS to properly integrate your code

    Login or Signup to reply.
  2. If we go to method_channel_messaging.dart, we see that the registerBackgroundMessageHandler implementation does not exist under iOs

    Let’s see

    https://github.com/firebase/flutterfire/blob/master/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/method_channel/method_channel_messaging.dart#L191

    @override
    Future<void> registerBackgroundMessageHandler(BackgroundMessageHandler handler) async {
        if (defaultTargetPlatform != TargetPlatform.android) {
            return;
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search