Why onLaunch method of FCM is get called multiple times - firebase

Every time i click on push notification it will redirect to desired screen but if I goes to homescreen where i configure fcm it will redirect to that desired screen automatically instead to stay on homescreen
Plugin used - firebase_messaging: ^7.0.3
#override
void onInit() {
// TODO: implement onInit
super.onInit();
//forNotification();
firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
print("onMessage for type: ${message['notification_type']}");
//print("onMessage for title: ${message['aps']['title']}");
//Get.to(ServiceNotificationDetails(message['data']['notification_id']));
/*Get.to(ServiceNotificationDetails(index, serviceNotificationList));*/
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
print("onMessage for type: ${message['data']['notification_type']}");
moveTo(message, message['data']['notification_type']);
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
print("onMessage for type: ${message['data']['notification_type']}");
},
);
isFinalMethod.value = init.read("petowner");
print("IN OR NOT ");
tabController =
new TabController(length: isFinalMethod.value ? 3 : 2, vsync: this);
setImage();
}
void moveTo(Map<String, dynamic> message,String notification_type)async{
print("Notification type is $notification_type");
switch (notification_type){
case "1":
Get.offAll(ServiceNotificationDetails(message['data']['notification_id']));
break;
case "2":
Get.offAll(PetItemDetails(0,message['data']['project_id']));
break;
case "3":
Get.offAll(ServiceNotificationDetails(message['data']['notification_id']));
break;
}
}
forNotification()async{
if (!initialized) {
firebaseMessaging.requestNotificationPermissions();
firebaseMessaging.configure();
// For testing purposes print the Firebase Messaging token
String token = await firebaseMessaging.getToken();
print("FirebaseMessaging token: $token");
initialized = true;
}
}
Here's the code of fcm config and navigaton method.

Related

Firebase messaging - Notifications are not sent when app is Closed or sleep in Flutter

I have built my app in flutter and I have implemented both LocalNotifications and FCM messaging.
this is my code:
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
registerNotification();
configLocalNotification();
}
void registerNotification() {
firebaseMessaging.requestNotificationPermissions();
firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
return ;
}, onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NotificationsScreen()));
},
onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
});
firebaseMessaging.getToken().then((token) {
print('token: $token');
FirebaseFirestore.instance
.collection('Consultant')
.doc(firebaseUser.uid)
.update({'deviceToken': token});
}).catchError((err) {
//Fluttertoast.showToast(msg: err.message.toString());
});
}
Future selectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
await Navigator.push(
context,
MaterialPageRoute<void>(builder: (context) => NotificationsScreen(payload: payload,)),
);
}
void showNotification(message) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
Platform.isAndroid
? 'it.wytex.vibeland_pro_app'
: 'it.wytex.vibeland_pro_app',
'Vibeland Pro',
'Vibeland Pro',
playSound: true,
enableVibration: true,
importance: Importance.max,
priority: Priority.high,
);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics);
print(message);
print(message['body'].toString());
print(json.encode(message));
await flutterLocalNotificationsPlugin.show(0, message['title'].toString(),
message['body'].toString(), platformChannelSpecifics,
payload: json.encode(message));
await flutterLocalNotificationsPlugin.show(
1, '📩 Hai ricevuto un messaggio 📩 ', 'Controlla subito le Tue notifiche 🔔🔔', platformChannelSpecifics,
payload: 'item x',
);
}
void configLocalNotification() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = new IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
var initializationSettings = new InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
I have built a function in firebase to push some New collections as notifications.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
const fcm = admin.messaging();
exports.sendNotification = functions.firestore
.document("Notifications/{id}")
.onCreate((snapshot) => {
const name = snapshot.get("name");
const subject = snapshot.get("subject");
const token = snapshot.get("token");
const payload = {
notification: {
title: "" + name,
body: "" + subject,
sound: "default",
click_action: "FLUTTER_NOTIFICATION_CLICK",
},
};
return fcm.sendToDevice(token, payload);
});
the version of firebase_messaging: ^7.0.3 and flutter_local_notifications: ^4.0.1
at the moment I don't upgrade due to some conflict with dependencies.
In this way I got both notifications when an app is open I get Local notifications correctly and when an app is in foreground and background I get Firebasemessaging according to the new collection added into my firestore.
The problem now comes when I close the app or the app after some minutes starts to sleep...
I can't get any notifications
To start again to get notifications, I need to run again the app and wake the app.
This is a problem with my app because my Apps notifications are very important and users need to get them always.
As you can on the FlutterFire documentation, foreground and background notification are handled differently by the plugin, so there are 2 thing you need to fix in your app.
First you need to prepare your Cloud Function to send background notifications as well as foreground, and in order to to that, you need to prepare your json to not only have a notification but also a data field, as follows:
const payload = {
notification: {
title: "" + name,
body: "" + subject,
sound: "default",
},
data: {
click_action: "FLUTTER_NOTIFICATION_CLICK"
}
};
Second, you are going to need configure your firebaseMassaging to receive background messages, like this:
firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
return ;
},
onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NotificationsScreen()));
},
onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
},
onBackgroundMessage: myBackgroundMessageHandler
);
And finally you need to create a handler that will manually handle background messages, following the example in the documentation you can do something like this:
Future<void> myBackgroundMessageHandler(RemoteMessage message) async {
print("Handling a background message: ${message}");
}
Adding the Line:
onBackgroundMessage: myBackgroundMessageHandler
Future<void> myBackgroundMessageHandler(RemoteMessage message) async {
print("Handling a background message: ${message}");
}
I got these error:
Nexus, [10.03.21 16:59]
[ File : app-release.apk ]
Amore, [10.03.21 17:09]
java.lang.RuntimeException: Unable to create service io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService: java.lang.RuntimeException: PluginRegistrantCallback is not set.
at android.app.ActivityThread.handleCreateService(ActivityThread.java:4023)
at android.app.ActivityThread.access$1600(ActivityThread.java:224)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1903)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7562)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.RuntimeException: PluginRegistrantCallback is not set.
at io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService.C(Unknown Source:70)
at io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService.onCreate(Unknown Source:40)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:4011)
... 8 more

Flutter: access SharedPreferences from onBackgroundMessage method of FirebaseMessaging

In my Flutter app I want to save data received from a Firebase Data Message to SharedPreferences.
I have the FirebaseMessaging object configured like this:
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
// this works fine
print("onMessage: ");
},
onLaunch: (Map<String, dynamic> data) {
print("onLaunch: ");
},
onResume: (Map<String, dynamic> data) {
print("onResume: ");
},
onBackgroundMessage: myBackgroundMessageHandler,
);
And this is the top-level myBackgroundMessageHandler method:
Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
// This doesn't work
print("background message"); // this isn't even printed!
SharedPreferences.getInstance().then(...) // here I have to save some data
}
The problem is that myBackgroundMessageHandler seems not to be called at all.
However, the notification is received on the phone.
I also tryed to remove the notification field from the message and in that case myBackgroundMessageHandler is called but the notification doesn't arrive. Is there a way to both receive the notification and trigger the method?

Flutter fcm redirect issue

Hi in one of my flutter project, I am using firebase messaging. First a splash screen and second, the main page of the application. In second page, I implemented the firebase.configure method in the init state as follows. The _navigateToItemDetail method leads to an another page
#override
void initState() {
super.initState();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
setState(() {
_newNotification = true;
});
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
_navigateToItemDetail(message);
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
_navigateToItemDetail(message);
},
);
and I cam calling the web service for this page after this. But the above method will launch after the webservice calls. So that will cause error in the page redirection. I just put a delay of 4 seconds in web service call, then it will works fine. Is there is any method to solve the issue ? async method available for firebase config ?
I think you need 'onBackgroundMessage'
firebaseMessaging.configure(
//...
onBackgroundMessage: Platform.isIOS ? null : myBackgroundMessageHandler
//...
)
//...
static Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async {
//Do here something
}
as you can see, it only work on android

How Should I access the data elements of the notification payload in flutter?

Below is the notification payload in cloud function for FCM notification in flutter application, I am not able figure out how to access the elements of the data:{} when the notification is received in flutter application
PAYLOAD
const payload = {
notification: {
title: `NOTIFICATION2 `,
body: contentMessage,
badge: '1',
sound: 'default'
},
data: {
click_action: 'FLUTTER_NOTIFICATION_CLICK',
notification2: notificationid2,
detail: detail,
senderAvatarURL: messageRecieverSenderAvatar,
category: 'default'
}
}
NOTIFICATION CODE
firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
Platform.isAndroid ? showNotification(message['notification']) : showNotification(message['aps']['alert']);
return;
}, onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return;
}, onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
});
you can use the below code to access data :
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
}
once you got the data map, you can parse it.
the package https://pub.dev/packages/firebase_messaging shows an example of handling data messages, check part with title
Define a TOP-LEVEL or STATIC function to handle background messages

Flutter firebase_messaging iOS app not receiving push-up notifications while app in foreground

I'm using flutter with "firebase_messaging 4.0.0+1".
Android version is working perfectly. On iOS, if app is in background, notifications work as intended. If app is in foreground, no call to onMessage is made...
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
print('on message $message');
},
onResume: (Map<String, dynamic> message) {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) {
print('on launch $message');
},
);
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(sound: true, badge: true, alert: true));
_firebaseMessaging.getToken().then((token) {
print('Token: ' + token);
});
I also faced similar issue when used stable flutter channel. After I switched to master
flutter channel master
the issue has gone.
Also it worths mentioning, that there are different payload handlers for Android and iOS.
For a payload:
{
"to": "<token>",
"notification": {
"title": "title_test1",
"body": "body_test_1"
},
"data": {
"id": "123",
"event": "test_event"
}
}
The data handler would be:
_firebaseMessaging.configure(
onMessage: (message) {
if (Platform.isAndroid) {
print("Android data handler; id: ${message['data']['id']}; event: ${message['data']['event']}");
} else if (Platform.isIOS) {
print("iOS data handler; id: ${message['id']}; event: ${message['event']}");
}
},
onLaunch: (message) {
...
},
onResume: (message) {
...
},
);

Resources