I've got a problem with Firebase Cloud Messaging notifications. When I want to send friend request in my Android app the other client doesn't receive a notification about this. And Firebase Functions log says:
TypeError: Cannot read property 'receiver_id' of undefined
at exports.sendNotification.functions.database.ref.onWrite.event (/user_code/index.js:9:35)
at cloudFunctionNewSignature (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:109:23)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:139:20)
at /var/tmp/worker/worker.js:730:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
Here is JavaScript code:
'use strict'
const functions = require('firebase-functions');
const admin = require ('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Notifications/{receiver_id}/{notification_id}')
.onWrite(event => {
const receiver_id = event.params.receiver_id;
const notification_id = event.params.notification_id;
console.log('We have a notification to send to: ', receiver_id);
if (!event.data.val) {
return console.log('A notification has been deleted from database: ', notification_id);
}
const deviceToken = admin.database().ref(`/Users/${receiver_id}/device_token`).once('value');
return deviceToken.then(result => {
const token_id = result.val();
const payload = {
notification:
{
title: "Friend Request",
body: "you have received a new friend request",
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response => {
console.log('This was the notification feature.');
});
});
});
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.database.ref('/Notifications/{receiver_id}/{notification_id}').onWrite((change, context) => {
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification : ', user_id);
const afterData = change.after.val();
if (!afterData){
return null;
}
const fromUser = admin.database().ref(`/Notifications/${user_id}/${notification_id}`).once('value');
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
console.log('You have a new notification from: ', from_user_id);
const deviceToken = admin.database().ref(`/Users/${user_id}/device_token`).once('value');
return deviceToken.then(result => {
const token_id = result.val();
const payload = {
notification: {
title: "New Friend Request",
body: "You've received a new Friend Request",
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response => {
console.log('This was the notification feature');
});
});
});
});
Try this code. It is taken from here uploaded by #xxxQDAxxx.
Related
I have this function which sends notification once there is certain change in my Db node. but i want to send multiple type of notifications for different actions. but when i deploy my function it overrides prior one and then i have tried all functions in single script but its not working properly
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/All_Users/{reciever_user_id}/CouponsUsedNotifications/{notification_id}')
.onWrite((data, context ) => {
const reciever_user_id = context.params.reciever_user_id;
const notification_id = context.params.notification_id;
console.log('Notification sent to : ', reciever_user_id)
if(!data.after.val()){
console.log('Notification Deleted : ', notification_id)
return null;
}
const deviceToken = admin.database().ref(`/All_Users/${reciever_user_id}/Credentials/device_token`).once('value');
return deviceToken.then(result =>
{
const token_id = result.val()
const payload = {
notification:
{
title: "Coupon Used",
body: `Your Coupon has been used..!!`,
icon: "default"
}
}
return admin.messaging().sendToDevice(token_id, payload).then(
Response => {
console.log('Notification Sent')
}
)
})})
exports.sendNotification = functions.database.ref('/All_Users/{reciever_user_id}/UserApprovalNotifications/{notification_id}')
.onWrite((data, context ) => {
const reciever_user_id = context.params.reciever_user_id;
const notification_id = context.params.notification_id;
console.log('Notification sent to : ', reciever_user_id)
if(!data.after.val()){
console.log('Notification Deleted : ', notification_id)
return null;
}
const deviceToken = admin.database().ref(`/All_Users/${reciever_user_id}/Credentials/device_token`).once('value');
return deviceToken.then(result =>
{
const token_id = result.val()
const payload = {
notification:
{
title: "Profile Approved",
body: `Your Profile has been Approved..!!`,
icon: "default"
}
}
return admin.messaging().sendToDevice(token_id, payload).then(
Response => {
console.log('Notification Sent')
}
)
})})
Found the solution...as i am not javascript developer thats why i was struggling but the solution i found is pretty simple. just install the files to new folder.
exports.sendNotification = function.
the sendNotification is the name of function just change it and deploy it
I am new to Cloud Functions so I having issues with below code, the error is in the last part where the console.log is mentioned, please assist what shall I been done to deploy the Function successfully, as I am following a tutorial there is no such error for the name.
'use-strict'
const functions = require('firebase-functions');
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
exports.sendNotifications = functions.firestore.document("users/{user_id}/notifications/{notification_id}").onWrite(event => {
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
return admin.firestore().collection("users").doc(user_id).collection("notifications").doc(notification_id).get().then(queryResult => {
const from_user_id = queryResult.data().from;
const message = queryResult.data().message;
const from_data = admin.firestore().collection("users").doc(from_user_id).get();
const to_data = admin.firestore().collection("user").doc(user_id).get();
return Promise.all([from_data, to_data]).then(result => {
const from_name = result[0].data().name;
const to_name = result[1].data().name;
const token_id = result[1].data().token_id;
const payload = {
notification: {
title: "Notification from:" + from_name,
body: message,
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(result =>{
console.log("notifcation sent");
});
});
});
});
By chaining your Promises and returning null in the last then(), as follows, you should solve your problem:
exports.sendNotifications = functions.firestore.document("users/{user_id}/notifications/{notification_id}").onWrite(event => {
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
return admin.firestore().collection("users").doc(user_id).collection("notifications").doc(notification_id).get()
.then(queryResult => {
const from_user_id = queryResult.data().from;
const message = queryResult.data().message;
const from_data = admin.firestore().collection("users").doc(from_user_id).get();
const to_data = admin.firestore().collection("user").doc(user_id).get();
return Promise.all([from_data, to_data]);
})
.then(result => {
const from_name = result[0].data().name;
const to_name = result[1].data().name;
const token_id = result[1].data().token_id;
const payload = {
notification: {
title: "Notification from:" + from_name,
body: message,
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload)
})
.then(messagingResponse => {
console.log("notification sent");
return null; //Note the return null here, watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/
});
});
You may have a look at the corresponding MDN documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#Chaining
Also, note that, in your code, it seems that you are not using the to_name constant.
How I can save a payload after sending them to specific Token in the specific node " Notifications/" to retrieve it in single screen later,
and it saves very well,
but when I got a notification I see providerName as a undefined when I declare a variable "providerName"
const functions = require("firebase-functions");
const admin = require("firebase-admin");
var serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://khadamatiapp-42657.firebaseio.com"
});
exports.acceptedOrder = functions.database
.ref("/AcceptedOrders/{pid}/{orderid}")
.onCreate(async (snapshot, context) => {
const registrationTokens = snapshot.val().userToken;
// const event = context.params;
const pid = context.params.pid;
console.log("#pid", pid);
const username = snapshot.val().username;
const userUid = snapshot.val().userUid;
var providerName;
admin
.database()
.ref(`providers/${pid}`)
.once("value")
.then(snapshot => {
providerName = snapshot.val().username;
console.log("pName", providerName); // here i got ProviderOne
});
console.log("#providerName", providerName); //here i got undefined
const payload = {
notification: {
from: pid,
to: userUid,
title: "New Order",
body: `Hi ${username}, You Order is Accepted from ${providerName}, check it now! `
//Hi userOne, You Order is Accepted from ***Undefined***, check it now!
}
};
try {
let notification = payload.notification;
const response = await admin
.messaging()
.sendToDevice(registrationTokens, payload)
.then(() => {
admin
.database()
.ref(`Notifications/${userUid}`)
.push({ notification });
});
console.log("Successfully sent message:", response);
} catch (error) {
console.log("Error sending message:", error);
}
return null;
});
Update
I have three functions and it's a trigger in the same root,
now acceptedOrderFromProvider that's invoked when I create new Element in the "AcceptedOrders" Root and send a push notification
and another function is CompletedOrderFromProvider that's trigger if the status changed, send a notification I use an onUpdate rigger but doesn't work well,
it's invoked when every element created or updated,
so how to force it to invoke just when some field "status" changed?
check here image
exports.acceptedOrderFromProvider = functions.database
.ref("/AcceptedOrders/{pid}/{orderid}")
.onCreate(async (snapshot, context) => {
const registrationTokens = snapshot.val().userToken;
// const event = context.params;
const pid = context.params.pid;
// console.log("#pid", pid);
const username = snapshot.val().username;
const userUid = snapshot.val().userUid;
var providerName;
admin
.database()
.ref(`providers/${pid}`)
.once("value")
.then(async snapshot => {
providerName = snapshot.val().username;
const payload = {
notification: {
from: pid,
to: userUid,
title: "Accepted Order",
body: `Hi ${username}, You Order is Accepted from ${providerName}, check it now! `
}
};
try {
let notification = payload.notification;
const response = await admin
.messaging()
.sendToDevice(registrationTokens, payload)
.then(() => {
admin
.database()
.ref(`Notifications/${userUid}`)
.push({ notification });
});
console.log("Successfully sent message:", response);
} catch (error) {
console.log("Error sending message:", error);
}
});
return null;
});
exports.cancelledOrderFromProvider = functions.database
.ref("/AcceptedOrders/{pid}/{orderid}")
.onDelete(async (snapshot, context) => {
const registrationTokens = snapshot.val().userToken;
// const event = context.params;
const pid = context.params.pid;
// console.log("#pid", pid);
const afterData = snapshot.val();
// console.log(afterData);
const username = snapshot.val().username;
const userUid = snapshot.val().userUid;
const nameOfProblem = snapshot.val().nameOfProblem;
var providerName;
admin
.database()
.ref(`providers/${pid}`)
.once("value")
.then(async snapshot => {
providerName = snapshot.val().username;
const payload = {
notification: {
from: pid,
to: userUid,
title: "Order Cancelled",
body: `Hi ${username}, ${providerName} Cancelled your Order "${nameOfProblem}"!`
}
};
try {
let notification = payload.notification;
const response = await admin
.messaging()
.sendToDevice(registrationTokens, payload)
.then(() => {
admin
.database()
.ref(`Notifications/${userUid}`)
.push({ notification });
});
console.log("Successfully sent message:", response);
} catch (error) {
console.log("Error sending message:", error);
}
});
return null;
});
exports.CompletedOrderFromProvider = functions.database
.ref("/AcceptedOrders/{pid}/{orderid}")
.onUpdate(async (snapshot, context) => {
console.log(snapshot.after.val());
const registrationTokens = snapshot.after.val().userToken;
const pid = context.params.pid;
const username = snapshot.after.val().username;
const userUid = snapshot.after.val().userUid;
const nameOfProblem = snapshot.after.val().nameOfProblem;
var providerName;
admin
.database()
.ref(`providers/${pid}`)
.once("value")
.then(async snapshot => {
providerName = snapshot.val().username;
const payload = {
notification: {
from: pid,
to: userUid,
title: "Order Completed",
body: `Hi ${username}, ${providerName} Completed your Order "${nameOfProblem}"! Check it Now`
}
};
try {
let notification = payload.notification;
const response = await admin
.messaging()
.sendToDevice(registrationTokens, payload)
.then(() => {
admin
.database()
.ref(`Notifications/${userUid}`)
.push({ notification });
});
console.log("Successfully sent message:", response);
} catch (error) {
console.log("Error sending message:", error);
}
});
return null;
});
Code inside a .then() is run asynchronously, so even though it appears above the rest of the code in the function, it may not be called until much later. Put all code that works with providerName inside the .then() callback to ensure it is called only after providerName has been retrieved:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
var serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://khadamatiapp-42657.firebaseio.com"
});
exports.acceptedOrder = functions.database
.ref("/AcceptedOrders/{pid}/{orderid}")
.onCreate(async (snapshot, context) => {
const registrationTokens = snapshot.val().userToken;
// const event = context.params;
const pid = context.params.pid;
console.log("#pid", pid);
const username = snapshot.val().username;
const userUid = snapshot.val().userUid;
var providerName;
admin
.database()
.ref(`providers/${pid}`)
.once("value")
.then(snapshot => {
providerName = snapshot.val().username;
const payload = {
notification: {
from: pid,
to: userUid,
title: "New Order",
body: `Hi ${username}, You Order is Accepted from ${providerName}, check it now! `
}
};
try {
let notification = payload.notification;
const response = await admin
.messaging()
.sendToDevice(registrationTokens, payload)
.then(() => {
admin
.database()
.ref(`Notifications/${userUid}`)
.push({ notification });
});
console.log("Successfully sent message:", response);
} catch (error) {
console.log("Error sending message:", error);
}
});
return null;
});
Code
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.database.ref(`/Notifications/{user_id}/{notification_id}/`).onWrite((change,context) =>{
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification to send to ', user_id);
if(!change.after.val()){
return console.log("A Notification has been deleted from the database", notification_id);
}
const fromUser = admin.database().ref('Notifications/${user_id}/${notification_id}').once('value');
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
console.log('You have a new notification from : ', from_user_id);
const userQuery = admin.database().ref('UserData/${from_user_id}/name').once('value');
return userQuery.then(userResult => {
const userName = userResult.val();
const deviceToken = admin.database().ref(`/UserData/${user_id}/TokenID`).once('value');
return deviceToken.then(result => {
const token_id = result.val();
const payload = {
notification: {
title: '${userName}',
body: "You have recieved a new Message",
icon: "default",
click_action : "com.appmaster.akash.messageplus_TARGET_NOTIFICATION"
},
data : {
from_user_id : from_user_id,
from_user_name : userName
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response =>{
return console.log('This was the notofication Feature');
});
});
});
I have no idea whats causing the error because i don't even understand the errors in command prompt and it doesn't even show where the error is or what it is... Can someone help me out with this please
You're using template literals, however it looks like you're using standard quotes in some places and not the back tick `. I can also see that you're referencing your user_id variable, however it isn't preceded by the $ symbol with curly braces
template literals need to look like this
`string here blah blah with ${variableHere} `
Code
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref(`/Notifications/{user_id}/{notification_id}/`).onWrite(event =>{
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
console.log('We have a notification to send to ', user_id);
if(!event.data.val()){
return console.log("A Notification has been deleted from the database", notification_id);
}
const deviceToken = admin.database().ref(`/UserData/${user_id}/TokenID`).once('value');
return deviceToken.then(result =>{
const token_id = result.val();
const payload ={
notification: {
title: "Friend request",
body: "You have recieved a new Friend Request",
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response =>{
return console.log('This was the notofication Feature');
});
});
});
Error
It just sucks that all code for an app can be done in android using java but the functions should be in javascript... New to the language so not sure what the error even means... Can someone help me solve it please?
Change this:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref(`/Notifications/{user_id}/{notification_id}/`).onWrite(event =>{
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
console.log('We have a notification to send to ', user_id);
if(!event.data.val()){
return console.log("A Notification has been deleted from the database", notification_id);
}
into this:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.database.ref(`/Notifications/{user_id}/{notification_id}/`).onWrite((change,context) =>{
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification to send to ', user_id);
if(!change.after.val()){
return console.log("A Notification has been deleted from the database", notification_id);
}
more info here:
https://firebase.google.com/docs/functions/beta-v1-diff