skip to Main Content

In my app, I have a default push notification topic "DEFAULT" which is subscribed by all the user. Whenever a new topic is created, I send a push notification over "DEFAULT" topic with a data/payload property containing the new notification topic name, to all the users. The app accepts the notification and takes out the new topic from the payload. If the new topic is valid for the user then it subscribes to it, otherwise ignores it. Below is the code that is working properly only when the app is in foreground state,

static void _handleForegroundMessages() async {
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      String? topicChannel = message.data['topic'];
      if (topicChannel != null && topicChannel == PredefinedNotificationTopic.topicCreated.name) {
        String newTopic = message.data['newTopicToSubscribe'];
        FCMHelper.addToUserTopicList(newTopic);
      }
      _showLocalNotification(message);
    })
};

However, the similar code for background/terminated state is throwing exception as below

E/flutter (24845): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
E/flutter (24845): #0      MethodChannelFirebase.app (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:193:5)
E/flutter (24845): #1      Firebase.app (package:firebase_core/src/firebase.dart:56:41)
E/flutter (24845): #2      FirebaseMessaging.instance (package:firebase_messaging/src/messaging.dart:32:47)
E/flutter (24845): #3      FCMService.subscribeToTopics (package:fourdrinier/service/fcm_service.dart:52:25)
E/flutter (24845): #4      FCMHelper.addToUserTopicList (package:fourdrinier/service/fcm_helper.dart:45:18)
E/flutter (24845): <asynchronous suspension>

Is it possible to achieve the same? or is there any work around?

Here is my background handler that I am calling using FirebaseMessaging.onBackgroundMessage(FCMService.backgroundHandler);

static Future<void> backgroundHandler(RemoteMessage message) async {
    String? topicChannel = message.data['topic'];
    debugPrint("Background notification with $topicChannel");
    if (topicChannel != null && topicChannel == PredefinedNotificationTopic.topicCreated.name) {
      String newTopic = message.data['newTopicToSubscribe'];
      FCMHelper.addToUserTopicList(newTopic);
    }
  }

3

Answers


  1. Chosen as BEST ANSWER

    It seems like the easiest solution was already mentioned in the exception message. No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()

    My issue got resolved after I added the Firebase.initializeApp() inside the background handler. Here is my final code.

    static Future<void> backgroundHandler(RemoteMessage message) async {
        await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // add this line here even if you have already added this inside main()
    
        String? topicChannel = message.data['topic'];
        debugPrint("Background notification with $topicChannel");
        if (topicChannel != null && topicChannel == PredefinedNotificationTopic.topicCreated.name) {
          String newTopic = message.data['newTopicToSubscribe'];
          FCMHelper.addToUserTopicList(newTopic);
        }
      }
    

  2. This function is called when the app is in background or terminated

    FirebaseMessaging.onBackgroundMessage((RemoteMessage message) async {
          // TODO implement your code here
        });
    
    Login or Signup to reply.
  3. You can do something like this using the workmanager package when you receive a push notification then you can launch a job which performs your subscription thing :

    @pragma('vm:entry-point') // Mandatory if the App is obfuscated or using Flutter 3.1+
    void callbackDispatcher() {
      Workmanager().executeTask((task, inputData) {
        print("Native called background task: $task"); //simpleTask will be emitted here.
        return Future.value(true);
      });
    }
    
    void main() {
      Workmanager().initialize(
        callbackDispatcher, // The top level function, aka callbackDispatcher
        isInDebugMode: true // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
      );
      Workmanager().registerOneOffTask("task-identifier", "simpleTask");
      runApp(MyApp());
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search