FirebaseMessaging callback not triggered while sending notification from cloud functions - firebase

client side code
final FirebasebaseMessaging _firebaseMessaging = new FirebaseMessaging();
_firebaseMessaging.configure(onMessage: (Map<String,dynamic> notification){
print("onMessage : $notification");
}, onResume: (Map<String,dynamic> notification){{
print("onResume: $notification");
}}, onLaunch: (Map<String,dynamic> notification){
print("onLaunch: $notification");
});
_firebaseMessaging.getToken().then((String token){
print("token is : $token");
});
server side
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var db = admin.firestore();
const payload = {
"notification": {
"body": postingUserDocumentSnapshot.data()['username'] + " commented on your post",
"title": "You got a comment",
"sound": 'enabled',
},
"data": {
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"senderId": postingUserDocumentSnapshot.data()['userId'],
"postID": context.params.postId,
"notificationType": "COMMENT",
},
};
admin.messaging().sendToDevice(receiverMessagingToken, payload);
I do receive notification in the system tray but the firebaseMessaging callbacks are not triggered. However if i send notification from google console those callbacks are triggered.
Can anyone explain me or suggest me on why those callbacks are not triggered while sending notification via admin.messaging().sendToDevice?

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

Is it possible to implement notification grouping/bundling using FCM in Flutter?

I try to implement group notification like this android group notification and ios group notification. But I can't able to do it. I tried this flutter_local_notification plugin too. but this works only when app open. not working on foreground(onResume) and background.
void registerNotification() {
_fcm.configure(
onMessage: (Map<String, dynamic> message) {
return;
},
onResume: (Map<String, dynamic> message) {
return;
},
onLaunch: (Map<String, dynamic> message) {
return;
},
onBackgroundMessage: backgroundMessageHandler);
}
payload
const payload = {
notification: {
title: title,
body: message,
},
data: {
click_action: "FLUTTER_NOTIFICATION_CLICK",
sound: "default"
},
android: {
priority: "high",
collapse_key: userName,//tried to add collapse_key for group notification
},
apns: {
headers: {
"apns-priority": "5",
},
},
token:token,
};
SOLUTION
I saw the react-native answer for this, you have to do same thing using Flutter with firebase_messaging react native answer
If you want to submit a group, you need to subscribe to a topic, in the documentation that mentions it, you would no longer send a single token, but would instead subscribe to a topic and submit it to that topic.

How can I get firebase notification data?

I can get Firebase message in onMessage when i'm in app like this:
{data: {}, notification: {body: how are you , title: hi}}
My code in initState:
firebaseMessaging.configure(
onLaunch: (Map<String,dynamic> msg){
print(" onLaunch called");
print(msg);
},
onResume: (Map<String,dynamic> msg){
print(" onResume called");
print(msg);
},
onMessage: (Map<String,dynamic> msg){
print(" onMessage called");
print(msg);
setState(() {
sms=msg['notification']['body'];
});
},
);
firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(
sound: true,
alert: true,
badge: true
)
);
firebaseMessaging.onIosSettingsRegistered.listen((IosNotificationSettings setting){
print("ios setting registed");
});
firebaseMessaging.getToken().then((token){
update(token);
});
}
update(String token){
print(token);
setState(() {
textValue=token;
});
I want to get Firebase message when app in background or closed,
how can I get that?
All you need to know is describe in the Receiving Message section of the Firebase Messaging package.
Methods onResume and onLaunch methods are fires only when the user clicks on the notification

Sending Push Notifications using expo + firebase

I am trying to send push notifications using expo tokens and firebase.
When I am trying to test the expo tokens by sending notification by expo notification tool it works fine.
But when I use firebase to check the push notification it does not works.
Here is my firebase function index.js file.
const functions = require('firebase-functions');
var fetch = require('node-fetch')
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendPushNotification = functions.database.ref('/UserOrders/').onCreate((snap, context) => {
const root = snap.data.ref.root
var messages = []
return root.child('/PushNotification').once('value').then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var expoToken = childSnapshot.val().expoToken;
messages.push({
"to": expoToken,
"sound": "default",
"body": "New enquiry. Please see!!"
});
});
return Promise.all(messages)
}).then(messages => {
console.log('messages', messages)
fetch('https://exp.host/--/api/v2/push/send', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(messages)
});
}).catch(reason => {
console.log('reason failure', reason)
})
});

Firebase messaging, message not recieved

My cloud function states it has sent a message successfully undefined messages were sent successfully but I don't receive it:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
var serviceAccount = require("./config.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://pushmessage-bd1eb.firebaseio.com"
});
const messaging = admin.messaging();
const message = {
data: { title: "Testing", body: "Test" },
token:
"fm8hZocb9X0:APA91bGANY8U1k7iXSAofh8PEtyA3SfkAvyvicjHbSzDC7s1DwzhCxBBhj5oeAhiZpNLFC1wUHOPX_C0vlGtUMv882EXxBjsM4qeBpFndka8kzir9kgmJnuPTRImx2cxUT53oXzJuAzB"
};
messaging.send(message).then(response => {
console.log(
response.successCount + " messages were sent successfully"
);
});
If I use the same token in the firebase dashboard to send a message, the message sends successfully.
How can I get my cloud function to send a message?
config.json:
{
"type": "service_account",
"project_id": "pushmessage-bd1eb",
"private_key_id": "xxx",
"private_key": "-----BEGIN PRIVATE KEY-----\nxxx-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-8dd2o#pushmessage-bd1eb.iam.gserviceaccount.com",
"client_id": "xxx",
"senderID": "388436954224",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-8dd2o%40pushmessage-bd1eb.iam.gserviceaccount.com"
}
Are you using admin.messaging().send()?
See:
https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#send
https://firebase.google.com/docs/reference/admin/node/admin.messaging.Message
https://firebase.google.com/docs/reference/admin/node/admin.messaging.Notification
Please try the following code.
Change data to notification.
And the admin.messaging().send() return string.
const message = {
notification: { title: "Testing", body: "Test" },
token:
"The registration token here"
};
admin.messaging().send(message).then(response => {
console.log(
response + " messages were sent successfully"
);
});
Or you can use admin.messaging().sendToDevice().
See:
https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#sendToDevice
https://firebase.google.com/docs/reference/admin/node/admin.messaging.MessagingPayload
https://firebase.google.com/docs/reference/admin/node/admin.messaging.MessagingDevicesResponse
Please try the following code.
const token= "The registration token here";
const payload = {
notification: { title: "Testing", body: "Test" }
};
admin.messaging().sendToDevice(token, payload).then(response => {
console.log(
response.successCount + " messages were sent successfully"
);
});

Resources