Firebase cloud function doesn't send push notification with async

780

I experienced a similar problem recently, and solved it by breaking out Android and iOS specific fields according to the Firebase docs :

   const message = {
  "notification": {
    "title": `New message from ${name}`,
    "body": message,
  },
  'apns': {
    'payload': {
      'aps': {
        'badge': 1,
      },
    },
  },
  'android':{
    'notification':{
      'notificationCount': 1,
    },
  },
  "tokens": tokens,
}
Share:
780
Admin
Author by

Admin

Updated on December 17, 2022

Comments

  • Admin
    Admin over 1 year

    My goal is to send a push notification when a user sends a message. I am trying to do this by retrieving all of the push tokens from the firestore database, and sending a multicast message using these tokens each time a new message is added to the realtime database.

    Works

    This first example works. There is no token retrieval, the tokens are hardcoded. I do receive the notifications.

    exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate((liveSnapshot, context) => {
        const name = context.params.messageId;
        const message = liveSnapshot.val().toString();
        const tokens = [
             "e6erA_qM...",
             "ePU9p_CI...",
        ];
        const payload = {
            notification: {
                title: `New message from ${name}`,
                body: message,
                badge: '1',
                sound: 'default'
            },
            tokens: tokens,
        }
        const res = admin.messaging().sendMulticast(payload);   
        console.log(`response: ${res}`);
    

    Doesn't work

    This doesn't work, I don't receive any notifications.

    exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate(async (liveSnapshot, context) => {
        const name = context.params.messageId;
        const message = liveSnapshot.val().toString();
        const snapshot = await admin.firestore().collection('users').get();
        const tokens = snapshot.docs.map(doc => doc.data().token);
        const payload = {
            notification: {
                title: `New message from ${name}`,
                body: message,
                badge: '1',
                sound: 'default'
            },
            tokens: tokens,
        }
        const res = await admin.messaging().sendMulticast(payload);     
        console.log(`response: ${res}`);
    

    I have verified that the tokens retrieved from the database are the same as the hardcoded ones with the following code.

    exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate(async (liveSnapshot, context) => {
        const hardcodedTokens = [
             "e6erA_qM...",
             "ePU9p_CI...",
        ];
        const snapshot = await admin.firestore().collection('users').get();
        const tokens = snapshot.docs.map(doc => doc.data().token);
        let same = true;
        hardcodedTokens.forEach(el => {
            if (!tokens.includes(el)) {
               same = false;
            }
        });
        console.log(same);
    })
    

    This logs true in the firebase cloud functions console.


    The function uses Node 12.