Reputation: 2249
I wanted to handle the background message of the FCM in the Flutter, but I got an error when FCM sent a message to the app in the background mode and made an error in the log.
pubspec.yaml:
firebase_core: ^0.7.0
firebase_messaging: ^8.0.0-dev.14
MainActivity.kt :
package com.mydomain.myproject
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
Application.kt :
package com.mydomain.myproject
import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingBackgroundExecutor
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingBackgroundService
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingPlugin
import io.flutter.plugins.pathprovider.PathProviderPlugin
class MyApplication : FlutterApplication(), PluginRegistrantCallback {
override
fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingBackgroundService.setPluginRegistrant(this)
FlutterFirebaseMessagingBackgroundExecutor.setPluginRegistrant(this)
}
override
fun registerWith(registry: PluginRegistry) {
PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"))
FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"))
FlutterFirebaseMessagingPlugin.registerWith(registry.registrarFor("plugins.flutter.io/firebase_messaging"))
}
}
Code of using fcm: I just called the _initFcm() in the initState() of the main app class. My purpose is when the app is in the background, the background FCM method must trigger, and I must save data of message in the preferences to do something with that when the app opens.
void _initFcm() {
Firebase.initializeApp();
FirebaseMessaging.onMessageOpenedApp.listen((message) {
Logger.log("_messaging onMessageOpenedApp: ${message}");
});
FirebaseMessaging.instance.getInitialMessage().then((value) {
Logger.log("_messaging getInitialMessage: ${value}");
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
Map<String, dynamic> data = message.data;
Logger.log("_messaging onMessage: ${message}");
Fcm.showNotification(notification.body, notification.title);
String type = data['type'];
if (type == "view") {
String notifPath = data['subject'];
notificationProvider.addPath(notifPath);
Logger.log('new notification added to notificationList: ${notifPath}');
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
Logger.log("_messaging onMessageOpenedApp: $message");
});
FirebaseMessaging.onBackgroundMessage((message) {
Logger.log("_messaging onBackgroundMessage: $message");
return;
});
}
Run log:
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'toRawHandle' was called on null.
E/flutter ( 5030): Receiver: null
E/flutter ( 5030): Tried calling: toRawHandle()
E/flutter ( 5030): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter ( 5030): #1 MethodChannelFirebaseMessaging.registerBackgroundMessageHandler (package:firebase_messaging_platform_interface/src/method_channel/method_channel_messaging.dart:181:42)
E/flutter ( 5030): #2 FirebaseMessagingPlatform.onBackgroundMessage= (package:firebase_messaging_platform_interface/src/platform_interface/platform_interface_messaging.dart:107:14)
E/flutter ( 5030): #3 FirebaseMessaging.onBackgroundMessage (package:firebase_messaging/src/messaging.dart:103:31)
E/flutter ( 5030): #4 _ChatrAppState._initFcm (package:parsian_chatr/app/ui/chatr_app.dart:90:23)
E/flutter ( 5030): #5 _ChatrAppState.initState (package:parsian_chatr/app/ui/chatr_app.dart:69:5)
E/flutter ( 5030): #6 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4765:58)
E/flutter ( 5030): #7 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4601:5)
E/flutter ( 5030): #8 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
E/flutter ( 5030): #9 Element.updateChild (package:flutter/src/widgets/framework.dart:3327:18)
E/flutter ( 5030): #10 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1252:16)
E/flutter ( 5030): #11 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1223:5)
E/flutter ( 5030): #12 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1165:17)
E/flutter ( 5030): #13 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2683:19)
E/flutter ( 5030): #14 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1164:13)
E/flutter ( 5030): #15 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:974:7)
E/flutter ( 5030): #16 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:955:7)
E/flutter ( 5030): #17 _rootRun (dart:async/zone.dart:1182:47)
E/flutter ( 5030): #18 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter ( 5030): #19 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter ( 5030): #20 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
E/flutter ( 5030): #21 _rootRun (dart:async/zone.dart:1190:13)
E/flutter ( 5030): #22 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter ( 5030): #23 _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1021:23)
E/flutter ( 5030): #24 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter ( 5030): #25 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
E/flutter ( 5030): #26 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
E/flutter ( 5030): #27 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
E/flutter ( 5030):
Upvotes: 45
Views: 45691
Reputation: 198
jus t add
@pragma('vm:entry-point')
right above
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
}
looks like this
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
}
void main() {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
Upvotes: 3
Reputation: 11
Just use a physical device instead of the emulator; this did it for me! Note: make sure to get the new token after using a real device
Upvotes: 1
Reputation: 370
I want to emphasize on AustrianDude comment that starting from flutter 3.3.0 , you need to add @pragma('vm:entry-point') to the handler method otherwise the dart won't be able to recoginze your handler
Upvotes: 1
Reputation: 624
In addition to mzafer answer,
add the below function definition on top of the file. [ outside of any class if exists ]
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
print("Handling a background message");
}
This worked for me.
Upvotes: 5
Reputation: 181
FirebaseMessaging.onMessageOpenedApp.listen((message) {
Logger.log("_messaging onMessageOpenedApp: ${message}");
});
has been called twice in your code
Upvotes: 1
Reputation: 851
Try this
In the file containing MainApp class add a handler. Remember to add it outside the class.
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
print("Handling a background message");
}
and replace
FirebaseMessaging.onBackgroundMessage((message) {
Logger.log("_messaging onBackgroundMessage: $message");
return;
});
with
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
Reference: https://firebase.flutter.dev/docs/messaging/usage/#background-messages
There are a few things to keep in mind about your background message handler:
It must not be an anonymous function. It must be a top-level function (e.g. not a class method which requires initialization).
Upvotes: 46