I am using a cloud functions to send a fcm message to the admins phone every time the bookings collection has a new document here:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.sendBookingNotification = functions.firestore
.document("bookings/{bookingId}")
.onCreate(async (snapshot, context) => {
// Get the newly added booking data
const bookingData = snapshot.data();
// Retrieve the admin's FCM token from Firestore
const adminFCMToken = await getAdminFCMToken(); // Implement the function to get admin's FCM token
if (adminFCMToken) {
// Send a notification to the admin
const message = {
data: {
title: "New Booking",
body: `A new booking has been added: ${bookingData.serviceTitle}`,
},
token: adminFCMToken,
};
console.log( `A new booking has been added: ${bookingData.serviceTitle}`);
try {
await admin.messaging().send(message);
console.log("Notification sent successfully.");
} catch (error) {
console.error("Error sending notification:", error);
}
}
});
// Function to get the admin's FCM token from Firestore
async function getAdminFCMToken() {
try {
const adminDoc = await admin.firestore().collection("users").where("userType", "==", "admin").get();
if (!adminDoc.empty) {
// Assuming there's only one admin, so we retrieve the first document found
const adminData = adminDoc.docs[0].data();
console.log("Admin Data:", adminData);
// Check if the admin document has an "fcmtoken" field
if (adminData.fcmToken) { // Update field name here
return adminData.fcmToken; // Update field name here
} else {
console.error("Admin document does not have an FCM token.");
return null;
}
} else {
console.error("No admin found in Firestore.");
return null;
}
} catch (error) {
console.error("Error fetching admin FCM token:", error);
return null;
}
}
And I am receiving the message here:
//making notifications available when the app closed
Future<void> handleBackgroundMessage(RemoteMessage message) async {
// Access title and body directly from message.data
final title = message.data['title'];
final body = message.data['body'];
print('Title: $title');
print('Body: $body');
print('Payload: ${message.data}');
}
class DBHandler {
//instance of firebase authentication
final FirebaseAuth auth = FirebaseAuth.instance;
//instance of firebase messenging
final _firebaseMessaging = FirebaseMessaging.instance;
//Function to initialise Notifications
Future<void> initNotification() async {
//request persmission from user
await _firebaseMessaging.requestPermission();
generateDeviceToken();
FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage);
// Save the FCM token to the user's Firestore document
}
generateDeviceToken() async {
String? fcmToken = await FirebaseMessaging.instance.getToken();
final userId = FirebaseAuth.instance.currentUser!.uid;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.update({'fcmToken': fcmToken});
}
I am Receiving the payload correctly the title and body are printing but I am still getting no notification showing up on my physical device.
2
Answers
message.notification
is only populated when you send a notification type message from the console. When you send from the Admin SDK, it is a data type message instead with a data payload.Read more about message types in the documentation to better understand the difference between these two message types.
If you want the title and body fields of the data payload you created, you should work only with
message.data
.It seems like you have not setup any code for a notification to show up – the most popular way to do this is using this package flutter_local_notifications
In your
handleBackgroundMessage
function you would use the above package, for example:You can check out this tutorial to setup the above