skip to Main Content

I’m still trying to figure out how receiving FCM works for Flutter application. According to this article I need to register a listener for a foreground notifications and background notifications. So in main.dart I have following functions:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  await initApp();
  runApp(const MyApp());
}

Future initApp() async {
  ...
  _initNotifications();
  ...
}

void _initNotifications() async {
  Logger.root.info("FCM token is: ${await FirebaseMessaging.instance.getToken()}");
  await FirebaseMessaging.instance.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    Logger.root.info('Got a message whilst in the foreground!');
    Logger.root.info('Message data: ${message.data}');

    if (message.notification != null) {
      Logger.root.info(
          'Message also contained a notification: ${message.notification!.toMap()}');
    }
  });
}

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  Logger.root.info("Handling a background message: ${message.messageId}");
}

When I send a notification from Firebase Composer while the application is active I see expected entries in the log. When I send a notification while the application is inactive I see the notification in the notifications bar but nothing is the log. So it seems the function _firebaseMessagingBackgroundHandler() isn’t called. Nevertheless if I comment out the line FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); I’m getting in the log:

02-24 12:38:26.714 25493 25493 D FLTFireMsgReceiver: broadcast received for message
02-24 12:38:26.769 25493 28429 W FLTFireMsgService: A background message could not be handled in Dart as no onBackgroundMessage handler has been registered.

Whilst when it’s registered I see following:

02-24 13:28:10.863 22057 22057 D FLTFireMsgReceiver: broadcast received for message
02-24 13:28:10.910 22057 23886 W FirebaseMessaging: Unable to log event: analytics library is missing
02-24 13:28:10.911 22057 23886 W FirebaseMessaging: Missing Default Notification Channel metadata in AndroidManifest. Default value will be used.

So that means background handler is expected but when it’s there it’s not called.
How do I ensure the background handler is called?

I’m a bit concerned about missing Default Notification Channel mentioned in the log. Should I specify it manually? I haven’t seen anything about this in Firebase docs for Flutter

And another related question. How do I ensure notification is handled when a device is locked? The article mentioned above mentions three possible states of applications:

State       Description 
=====       ===========
Foreground  When the application is open, in view and in use. 
Background  When the application is open, but in the background (minimized). 
            This typically occurs when the user has pressed the "home" button 
            on the device, has switched to another app using the app switcher, 
            or has the application open in a different tab (web). 
Terminated  When the device is locked or the application is not running.

However it doesn’t say anything about handling notifications when application is in terminated state.

2

Answers


  1. Chosen as BEST ANSWER

    Ok, it turned out my code works just fine. Only problem is the logging line:

    @pragma('vm:entry-point')
    Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
      Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
      /////// this line is wrong /////////////
      Logger.root.info("Handling a background message: ${message.messageId}");
    }
    

    Most likely the problem is with logging facility. For the main isolate I have defined a logging listener that prints formatted log entries. But I'm pretty sure background message isolate doesn't communicate with one and hence doesn't log anything. That's another issue to solve.

    But I can confirm the code works and handles foreground messages and background ones event if device is turned off.

    As for terminated application notifications are still coming but they have to be enabled manually.

    Thanks to everyone who helped with solving the problem.


  2. call your firebase background messaging function in main()

    Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
      await Firebase.initializeApp();
      log('Handling a background message ${message. messageId}');
    }
    
    
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      await FirebaseMessaging.instance.getInitialMessage();
      FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); 
      
      requestPermission();
      runApp(const MyApp());
    }
    
    Future<Map<Permission, PermissionStatus>> requestPermission() async {
      Map<Permission, PermissionStatus> statuses =
          await [Permission.notification].request();
      return statuses;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search