How to Use Firebase Functions to Send Fcm to User

How can I use Firebase Functions to send FCM to user?

Firebase SDK for Cloud Functions includes the Firebase Admin SDK, you can find an example that we made here Send Firebase Cloud Messaging notifications for new followers

In brief:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.foo = functions.database.ref('/bar').onWrite(event => {
const tokens = ...;
const payload = ...;
return admin.messaging().sendToDevice(tokens, payload);
})

Sending FCM messages to web apps through firebase cloud functions

Sending messages to a web app is no different from sending it to a native mobile app, so the sending part of guidance you've found is equally applicable. The Firebase documentation even contains an example of sending notifications on a Realtime Database trigger, and doing the same for Firestore would not be much different.

If you're having a specific problem sending messages, I recommend showing what you tried, and what isn't working about it.


Update: your code doesn't work (no matter what sort of device you send the notification to), because you're not handling the asynchronous nature of get() in your code.

The simplest way to fix that is to use await there too, just like you do when calling sendToDevice. So:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/users/{doc}/{Hears}')
.onUpdate(async (change, context) => {
const db = admin.firestore();
const doc = await db.collection('users').doc(context.params.userId).get();
const fcmToken = doc.data().usrTkn;
const payload = {
notification: {
title: 'You have a new message.',
body: 'Open your app'
}
};
const response = await admin.messaging().sendToDevice(fcmToken, payload);
console.log(response);
})

I highly recommend spending some time on learning about asynchronous calls, closures, async/await, and how to debug something like this by adding logging.

cloud function to send FCM from specific app

You can sent notification based on topic. For example project-one-topic-unique-user-id and project-two-topic-unique-user-id. So now send notification based on topic

let message = {
"topic": "project-two-topic-unique-user-id"
"notification": {
title: theTitle,
sound: 'default',
}
}
}

admin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});

Send notification to one user with firebase cloud function node

Firebase Cloud Messaging has no concept of a user. Instead it can send messages to:

  • Specific app instances (so your specific app as installed on one specific device), as identified by an FCM/device token.
  • A group of app instances/tokens, as defined by your application logic.
  • A specific topic, to which app instances can then subscribe.

It's up to your application logic to decide how to map from your user ID to one of these options. The most common are to:

  • Store the device token(s) and your user ID in your own database, then look up the device token(s) for a user when needed and fill them in to the API call you already have.
  • Use a specific topic for each user ID, subscribe the application to that when it starts, and then send a message to that topic when needed. Note that anyone can subscribe to any topic though, so this approach would allow folks to receive message for anyone whose user ID they know.

Firebase send user to user notification without using cloud function or personal server

well this is not possible as it would require API key as mentioned by Doug in the comment. and putting that in client code would make blunder.

i m just making a guess and it is quite off topic but it might help someone in future if you dont want to read user FCM id again and agin from firestore as it might increase bill. you can create topics in FCM and subscribe the client to it. this way you can reduce the number of reads and suffice the purpose.

FCM Docs

Firebase functions cloud messaging notification not being recieved

Did you notice how your code never logs this message?

Successfully sent message

That's because both loading from Firestore, and sending messaging through Cloud Messaging are asynchronous calls. So your response.send("Notification sent !") runs before the data is ever retrieved from the database, and Cloud Functions at that point terminates your code to prevent charging after you say that you are done.

If you have asynchronous operations in your code, you need to return a promise from the top-level of your code that resolves/rejects when all asynchronous code has completed. So in your case that means the promise should only resolve once you've loaded the data from Firestore, and sent the messages.


Let's start with a simple example. Say that you want to only send a single message, no matter how many documents are in the database.

exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
return db.collection("users") // Add return here
.where("bananas", "==", 1666).get().then((result) => {
if (result.size > 0) {
const doc = result.docs[0]; // Get the first result
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
return fcm.send(payload).then((response) => { // Add return here
console.log("Successfully sent message: "+
doc.data().NotToken+ " ", response);
response.send("Notification sent !"); // Move this call here
return {success: true};
}).catch((error) => {
// TODO: Send an error back to the caller
return {error: error.code};
});
}
});
});

So the top-level code now returns the result from loading data from Firestore, and in there, we return the call from calling FCM, which then in turn returns return {success: true};. When returning promises, the results bubble up - so you can typically just keep returning the nested results.

You'll also not that we've moved the response.send into the code that runs after calling FCM, as we don't want to send a result back to the caller until the FCM call is done.


The above is the simple variant, because in reality you have multiple documents, and you are only done once all of them are done.

For that we are going to use Promise.all(), which takes an array of promises and resolves once all those promises resolve. So we're going to capture all the calls to FCM (which returns a promise) and collection them in an array, that we then pass to Promise.all().

exports.sendNotification = functions.https.onRequest((request, response) => {
const db = admin.firestore();
const fcm = admin.messaging();
return db.collection("users")
.where("bananas", "==", 1666).get().then((result) => {
if (result.size > 0) {
let promises = [];
result.forEach((doc) => {
const payload = {
token: doc.data().NotToken,
notification: {
title: "iam a notification",
body: "Yay",
icon: "https://cdn1.iconfinder.com/data/icons/logos-brands-in-colors/231/among-us-player-white-512.png",
},
};
promises.push(fcm.send(payload))
});
return Promise.al(promises).then((results) => {
console.log("Successfully sent messages");
response.send("Notification sent !");
return {success: true};
});
}
});
});

While this may be a lot to grok all at once, handling asynchronous behavior is quite well covered in the Firebase documentation on terminating functions, in this video series on Learn JavaScript Promises with Cloud Functions, and in quite a few tutorials out there - so I recommend spending some time on those to get to grips with asynchronous code.



Related Topics



Leave a reply



Submit