Foreground Push Notification - firebase

The push-notification forces the app to another screen without even the user clicking on the notification, whenever I send a notification using cloud messaging from firebase.
I want the user to first tap on the notification, which will then push to another screen. The code below is for the app running in the foreground, where I am facing the issue.
Ty in advance. It's for ANDROID*
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
final routeFromMessage = message.data['route'];
Navigator.of(context).pushNamed(routeFromMessage);
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin!.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel!.id,
channel!.name,
channel!.description,
// one that already exists in example app.
icon: 'launch_background',
),
),
payload: message.data['route'],
);
}
});

Related

How to stack fcm push notification and display it when internet gets on , Flutter firebase

I am using fcm for push notification , and i am trying to stack the notifications when the internet is off ,
What is happening now is
When the app doesn't have internet and the app if receives more than one notification , when the interent is switched on , only the latest notification is shown.
What I want to achieve is
When the app doesn't have internet and the app if receives more than one notification , when the interent is switched on , I want to show all the notifications not just the latest one.
I am presently using the following code snippets.
// Background and also terminated
FirebaseMessaging.instance.getInitialMessage().then((value) =>
Navigator.push(
context, MaterialPageRoute(builder: (context) => DummyScreen())));
// Background not terminated
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print(
"The message from within the onMessageOpenedApp and i am within the home_page is : " +
message.notification!.title.toString());
Navigator.push(
context, MaterialPageRoute(builder: (context) => DummyScreen()));
});
// When app is in foreground
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
// TODO add a proper drawable resource to android, for now using
// one that already exists in example app.
icon: 'launch_background',
),
),
);
}
});

Local Notifications Plugin showing notification twice

I want to play a custom notification sound only when app is in background or terminated state and if i implement onBackgroundMessage i am getting two notifications one automatic (default sound) and another manual(with custom sound)
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}');
if (message.notification != null) {
print(message.notification.title);
print(message.notification.body);
flutterLocalNotificationsPlugin.show(
message.notification.hashCode,
message.notification.title,
message.notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
playSound: true,
importance: Importance.max,
priority: Priority.high,
sound: RawResourceAndroidNotificationSound('sound'),
),
iOS: IOSNotificationDetails()
));
}
// Create a notification for this
}

Push-Notification pushes to the new screen without even clicking on the notification(while app is running in the FOREGOUND)

The push-notification forces the app to another screen without even the user clicking on the notification, whenever I send a notification using cloud messaging from firebase.
I want the user to first tap on the notification, which will then push to another screen.
The code below is for the app running in the foreground, where I am facing the issue.
Ty.
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
final routeFromMessage = message.data['route'];
print('A new onMessage event was published!');
Navigator.of(context).pushNamed(routeFromMessage);
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin!.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel!.id,
channel!.name,
channel!.description,
// one that already exists in example app.
icon: 'launch_background',
),
),
payload: message.data['route'],
);
}
});
This line is pushing to the new route as soon as notification received. Just remove it.
Navigator.of(context).pushNamed(routeFromMessage);

How to configure Firebase Messaging with latest version in Flutter?

I was using the below line of code for firebase messaging configuration for flutter noticification configuration , but now after integrating to the latest version of the firebase messaging it is giving me error
CODE LINE
messaging.configure(onMessage: (Map<String, dynamic> message){}
ERROR in DART Analysis
error: The method 'configure' isn't defined for the type 'FirebaseMessaging'.
FirebaseMessaging.configure() is removed by firebase team:
Reason:
The previous implementation of configure() caused unintended side effects if called multiple times (either to register a different handler or remove handlers). This change allows developers to be more explicit about registering handlers and removing them without affecting others via Streams.
Use FirebaseMessaging.onMessage method to get messages
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
});
Use FirebaseMessaging.onMessageOpenedApp as a replacement for onLaunch and onResume handlers.
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
});
Please check following example.
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/firebase_messaging/example/lib/main.dart
#override
void initState() {
super.initState();
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
if (message != null) {
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
}
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null && android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
// TODO add a proper drawable resource to android, for now using
// one that already exists in example app.
icon: 'launch_background',
),
));
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
});
}
Building on Jitesh's answer, for me implementation of getInitialMessage is needed to make the navigation works when the app is terminated (replacement for onLaunch)
// workaround for onLaunch: When the app is completely closed (not in the background) and opened directly from the push notification
FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage message) {
print('getInitialMessage data: ${message.data}');
_serialiseAndNavigate(message);
});
// onMessage: When the app is open and it receives a push notification
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print("onMessage data: ${message.data}");
});
// replacement for onResume: When the app is in the background and opened directly from the push notification.
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('onMessageOpenedApp data: ${message.data}');
_serialiseAndNavigate(message);
});
Updated One:
FirebaseMessagingService is important to get started in the beginning of app. And for that sake, you need to follow this:
Declare this function first :
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
debugPrint("Firebase Messaging firebase is initialized");
await Firebase.initializeApp();
}
And call this function in the main(){} of app:
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
And then you will be able to use these functions:
FirebaseMessaging.onMessage method to get messages
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
});
FirebaseMessaging.onMessageOpenedApp as a replacement for onLaunch and onResume handlers.
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
Navigator.pushNamed(context, '/message',
arguments: MessageArguments(message, true));
});
Event handling:
Event handling has been reworked to provide a more intuitive API for developers. Foreground-based events can now be accessed via Streams:
FirebaseMessaging.onMessage Returns a Stream called when an incoming FCM payload is received whilst the Flutter instance is in the foreground, containing a [RemoteMessage].
FirebaseMessaging.onMessageOpenedApp Returns a [Stream] that is called when a user presses a notification displayed via FCM. This replaces the previous onLaunch and onResume handlers.
FirebaseMessaging.onBackgroundMessage() Sets a background message handler to trigger when the app is in the background or terminated.
IosNotificationSettings:

Send push notifications using Firebase and OneSignal

Not sure if this is possible, but I have an existing Ionic 3 app which uses Firebase as a backend. Maybe it's just me, I'm not able to integrate Google login, Facebook login and push notifications in the same app. Been trying for a few days now.
I was able to install OneSignal and send push notifications to an Android device, but I want to send them programatically using tokens which are saved for each device, not from the OneSignal dashboard.
This is what I use in Firebase Cloud Functions to send notifications. Can it be modified to send the notification to OneSignal and then to each device?
`function sendFcm(userID, eventSnapshot, eventID) {
const getDeviceTokensPromise = admin.database().ref(`/fcmTokens/${userID}/`).once('value');
return Promise.all([getDeviceTokensPromise]).then(result => {
const tokensSnapshot = result[0];
const payload = {
"notification": {
"title": "Your invitation has arrived",
"body": eventSnapshot.name,
"sound": "default",
// "click_action": "FCM_PLUGIN_ACTIVITY",
"icon": "fcm_push_icon"
},
"data": {
"eventId": eventID,
"uid": userID,
"eventObj": JSON.stringify(eventSnapshot),
"notificationType": "newEventNotification"
}
};
const tokens = Object.keys(tokensSnapshot.val());
console.log(tokens);
// Send notifications to all tokens.
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
console.log(tokens[index]);
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens which are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
tokensToRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
}
}
});
return Promise.all(tokensToRemove);
});
})
}`
After searching a bit, I found the OneSignal API. Seems that I just need to save the player id and send it or mutiple in an array to onesignal.com/api/v1/notifications. More details here: https://documentation.onesignal.com/reference#section-send-based-on-onesignal-playerids-create-notification

Resources