Reputation:
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.
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}`);
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.
Upvotes: 3
Views: 2357
Reputation: 3610
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,
}
Upvotes: 1
Reputation:
The following code works.
async function getTokens() {
const snapshot = await admin.firestore().collection('users').get();
return snapshot.docs.map(doc => doc.data().token);
}
exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate(async (snapshot, context) => {
const name = context.params.messageId;
const message = snapshot.val().toString();
const tokens = await getTokens();
const payload = {
notification: {
title: `New message from ${name}`,
body: message,
},
tokens: tokens,
};
await admin.messaging().sendMulticast(payload);
})
I logged my response like below:
const res = await admin.messaging().sendMulticast(payload);
console.log('response:', JSON.stringify(res));
This logged the following:
response: {"responses":[{"success":false,"error":{"code":"messaging/invalid-argument","message":"Invalid JSON payload received. Unknown name \"sound\" at 'message.notification': Cannot find field."}},{"success":false,"error":{"code":"messaging/invalid-argument","message":"Invalid JSON payload received. Unknown name \"sound\" at 'message.notification': Cannot find field."}}],"successCount":0,"failureCount":2}
Based on this, I believe the problem was the sound
argument in the notification part of the payload. It works after removing it.
Upvotes: 1