firebaseMessagingBackgroundHandler not triggered when app is in background
Asked Answered
R

4

6

I assumed I followed all the steps to handling background notifications from firebase in flutter. I have created a top-level function that I am expecting to be triggered whenever a notification comes in. However, the function is never triggered.

Here's the top-level background handler function that exists in my home page widget but outside the class:

Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  // ignore: avoid_print
  print('A background message just showed up :  ${message.messageId}');

  // update SQLite
  var result = await PageService.instance
      .add(PageService.instance.convertToPage(message.data));
  print('added to db: ${result}');
}

Here is my home page init state that calls a function to initialize firebase messgaging:

@override
  void initState() {
    super.initState();

    _initializeFirebaseMessaging();
  }

And then here is the _initializeFirebaseMessaging function that is defined in the home page class as well:

void _initializeFirebaseMessaging() {
    FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);

    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      print('new notification arrived');
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;

      // update SQLite
      var result = await PageService.instance
          .add(PageService.instance.convertToPage(message.data));
      print('added to db: ${result}');

      if (notification != null && android != null) {
        // show notification
        flutterLocalNotificationsPlugin.show(
            notification.hashCode,
            notification.title,
            notification.body,
            NotificationDetails(
              android: AndroidNotificationDetails(
                channel.id,
                channel.name,
                color: Colors.blue,
                playSound: true,
                icon: '@mipmap/ic_launcher',
              ),
            ));
      }
    });
  }

The onmessage.listen works fine as I get notificationd and handle them while I'm in the app, but the background handler is not triggered at all.

I would appreciate any help!

Rogelioroger answered 22/9, 2022 at 16:30 Comment(2)
Could you plz print only print('A background message just showed up') to start with? So that we know if THAT functions... – Garrulous
And I agree with another answer, WidgetsFlutterBinding.ensureInitialized() should not be there, because this function is supposed to be triggered while the app is NOT bound... So speaking of that, plz put your print statement FIRST in the function! So that you'll know if it was at all triggered, even if something went wrong later. – Garrulous
D
1

You have to call FirebaseMessaging.onBackgroundMessage inside your main() not in initState()

Despatch answered 23/9, 2022 at 4:6 Comment(1)
I was thinking that too... It's what I do, for sure! – Garrulous
L
1

onMessage handles foreground notification

onMessageOpenedApp handles background notification

Instead of using onMessage for handling Background notifications, add another function block of FirebaseMessaging with onMessageOpenedApp, if you want notification while the app is in background, like this:

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message){...})

onMessage only works when the app is in foreground. If you want notification while the app is in the terminated state you can use:

FirebaseMessaging.instance.getInitialMessage().then((message){...})

Update your firebaseMessagingBackgroundHandler to this:

Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  
  // ignore: avoid_print
  print('A background message just showed up :  ${message.messageId}');

  // update SQLite
  var result = await PageService.instance
      .add(PageService.instance.convertToPage(message.data));
  print('added to db: ${result}');
}

And finally, the main() should look like this:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Add Firebase Initialization:
  await Firebase.initializeApp();
  // This will initialize a new Firebase instance.

  // Background message handler
  FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
  
  runApp(const App());
}

You should call FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); from within main(), not from Homepage initState(){}.

Luncheon answered 1/10, 2022 at 18:49 Comment(4)
You can't use onMessageOpenedApp instead of onMessage! onMessageOpenedApp is only triggered when the app was literally opened because a user clicked a notification, which is a very different scenario from when a message comes in while the app is in foreground, which is when onMessage is fired! (The latter case doesn't even automatically produce a notification.) Otherwise, this is a great answer with lots of good tips. πŸ™‚ – Garrulous
Also getInitalMessage is meant to tell the app what to do when it was opened by clicking a notification while the app was in terminated. I.e. the notification is already there! (As for onMessageOpenedApp.) This function only makes sure the app gets the data from the notification, so that it can do stuff with it. – Garrulous
I see, I wasn't clear enough! What I meant was, use onMessageOpenedApp besides onMessage if he wants both foreground and background notification. Lemme update the answer! As for the getInitialMessage description you gave, I didn't know it worked like that. Thank you so much, maam! – Luncheon
Ok, but onMessageOpenedApp works very much THE SAME as getInitialMessage... You can see, for example, that they both take a message as an argument! The only difference is that the former is triggered when app wakes up from background, whereas the latter is triggered when app wakes up from terminated. – Garrulous
A
0

try: after main func

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  ...
}

and remove WidgetsFlutterBinding.ensureInitialized(); in firebaseMessagingBackgroundHandler

Alexander answered 27/9, 2022 at 9:36 Comment(0)
M
0

Make sure you have followed these steps for your onBackgroundMessage handler:

  1. It must not be an anonymous function.
  2. It must be a top-level function (e.g. not a class method which requires initialization).
  3. When using Flutter version 3.3.0 or higher, the message handler must be annotated with @pragma('vm:entry-point') right above the function declaration (otherwise it may be removed during tree shaking for release mode).

Source: https://firebase.google.com/docs/cloud-messaging/flutter/receive#apple_platforms_and_android

Mcginn answered 10/4 at 10:13 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.