27

I am trying to make a cloud function that sends a push notification to a given user.

The user makes some changes and the data is added/updated under a node in firebase database (The node represents an user id). Here i want to trigger a function that sends a push notification to the user.

I have the following structure for the users in DB.

Users

 - UID
 - - email
 - - token

 - UID
 - - email
 - - token

Until now i have this function:

exports.sendNewTripNotification = functions.database.ref('/{uid}/shared_trips/').onWrite(event=>{
const uuid = event.params.uid;

console.log('User to send notification', uuid);

var ref = admin.database().ref('Users/{uuid}');
ref.on("value", function(snapshot){
        console.log("Val = " + snapshot.val());
        },
    function (errorObject) {
        console.log("The read failed: " + errorObject.code);
});

When i get the callback, the snapshot.val() returns null. Any idea how to solve this? And maybe how to send the push notification afterwards?

AL.
  • 36,815
  • 10
  • 142
  • 281
Tudor Lozba
  • 736
  • 1
  • 6
  • 9
  • Does the console.log of the uuid show the correct value? – Jen Person Jun 14 '17 at 14:39
  • Yes, the uuid is correct. – Tudor Lozba Jun 14 '17 at 14:54
  • Use back-ticks to substitute the value of `uuid` in your ref: `admin.database().ref(\`Users/${uuid}\`)`. Also you should use `once()` instead of `on()`. `on()` leaves the listener attached; not something you want in a cloud function. – Bob Snyder Jun 14 '17 at 15:23
  • 2
    Also, your function should return a promise that indicates to Cloud Functions when your work is done and it's safe to clean up. If you do async work without returning a promise, it will not work the way you want. It might be a good idea to go over these video tutorials to learn more: https://www.youtube.com/playlist?list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM – Doug Stevenson Jun 14 '17 at 17:35
  • Doug is correct - with Cloud Functions you should be returning a promise so that it can watch the chain execute and then stop the instance when it is done. Because it has no way of knowing that async work is happening in this case, the function is completing before the async work is actually completed. – Andrew Breen Jun 15 '17 at 07:58

5 Answers5

40

I managed to make this work. Here is the code that sends a notification using Cloud Functions that worked for me.

exports.sendNewTripNotification = functions.database.ref('/{uid}/shared_trips/').onWrite(event=>{
    const uuid = event.params.uid;

    console.log('User to send notification', uuid);

    var ref = admin.database().ref(`Users/${uuid}/token`);
    return ref.once("value", function(snapshot){
         const payload = {
              notification: {
                  title: 'You have been invited to a trip.',
                  body: 'Tap here to check it out!'
              }
         };

         admin.messaging().sendToDevice(snapshot.val(), payload)

    }, function (errorObject) {
        console.log("The read failed: " + errorObject.code);
    });
})
Jonathan Simonney
  • 585
  • 1
  • 11
  • 25
Tudor Lozba
  • 736
  • 1
  • 6
  • 9
  • is there any way to send messages to a topic using firebase cloud function? – Jerin A Mathews Oct 15 '17 at 11:53
  • will this code send notification to all the users? What if I wants to send notification to only one user like whatsapp message notification. – Deepak Gautam Oct 17 '18 at 10:36
  • @DeepakGautam This will only send to one specific device. Note sendToDevice is a legacy method. See https://firebase.google.com/docs/cloud-messaging/admin/send-messages – Codelicious Jan 04 '19 at 20:53
  • 3
    I'm using the above cloud function to send notification, but I don't know how to receive for iOS. Could somebody please let me know how to receive the above notification and display its content to the user? – Arjun May 07 '19 at 02:18
9

Just answering the question from Jerin A Mathews... Send message using Topics:

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp(functions.config().firebase);

//Now we're going to create a function that listens to when a 'Notifications' node changes and send a notificcation
//to all devices subscribed to a topic

exports.sendNotification = functions.database.ref("Notifications/{uid}")
.onWrite(event => {
    //This will be the notification model that we push to firebase
    var request = event.data.val();

    var payload = {
        data:{
          username: request.username,
          imageUrl: request.imageUrl,
          email: request.email,
          uid: request.uid,
          text: request.text
        }
    };

    //The topic variable can be anything from a username, to a uid
    //I find this approach much better than using the refresh token
    //as you can subscribe to someone's phone number, username, or some other unique identifier
    //to communicate between

    //Now let's move onto the code, but before that, let's push this to firebase

    admin.messaging().sendToTopic(request.topic, payload)
    .then((response) => {
        console.log("Successfully sent message: ", response);
        return true;
    })
    .catch((error) => {
        console.log("Error sending message: ", error);
        return false;
    })
})
//And this is it for building notifications to multiple devices from or to one.
Gsilveira
  • 91
  • 1
  • 4
  • Hello, what if I have a specific topic I want to send to? Say, like some people subscribed to GoodMorning topic and another group NoonTopic. Kindly assist. – Joseph Wambura Mar 21 '19 at 12:30
  • @Gsilveira can you check this,https://stackoverflow.com/questions/56656303/cloud-function-cant-log-anything – DevAS Jun 18 '19 at 20:47
1

Return this function call.

return ref.on("value", function(snapshot){
        console.log("Val = " + snapshot.val());
        },
    function (errorObject) {
        console.log("The read failed: " + errorObject.code);
});

This will keep the cloud function alive until the request is complete. Learn more about returning promises form the link give by Doug in the comment.

Aawaz Gyawali
  • 3,244
  • 5
  • 28
  • 48
1

Send Notification for a Topic In Cloud function

Topics a basically groups you can send notification for the selected group

    var topic = 'NOTIFICATION_TOPIC';
    const payload = {
        notification: {
            title: 'Send through Topic',
            body: 'Tap here to check it out!'
        }
   };

   admin.messaging().sendToTopic(topic,payload);

You can register the device for any new or existing topic from mobile side

Lahiru Pinto
  • 1,621
  • 19
  • 20
  • Thanks this worked great! How can I modify it? Sound, badge etc. – submariner Jul 14 '22 at 18:50
  • Try this - https://firebase.google.com/docs/cloud-messaging/http-server-ref#:%7E:text=Table%202c.%20Web%20(JavaScript)%20%E2%80%94%20keys%20for%20notification%20messages – Lahiru Pinto Jul 14 '22 at 19:39
0
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);


exports.sendNotificationToTopic = 
functions.firestore.document('Users/{uuid}').onWrite(async (event) => {

//let title = event.after.get('item_name');
//let content = event.after.get('cust_name');
var message = {
    notification: {
        title: "TGC - New Order Recieved",
        body: "A New Order Recieved on TGC App",
    },
    topic: 'orders_comming',
};

let response = await admin.messaging().send(message);
console.log(response);
});

For sending notifications to a topic, The above code works well for me, if you have any doubt, let me know.