Reputation: 240
I am writing my first cloud function to send a push notification when a new user signs up with my android app. I have done the basics like installing Node and firebase cli and got my project initialized.
I have written this test function below to log the user id of any user along with their token, who signs up and deployed to firebase.
exports.sendSignUpNotification =functions.database.ref('/users/{userId}').onWrite((change, context) => {
const user_id = context.params.userId;
//const notifID = context.params.notification_id;
console.log("User id at signup:\t", user_id);
//console.log("Notification id at signup:\t", notifID);
let token = admin.database().ref(`/users/{userId}/id_token`).once('value');
console.log("User id token:\t", token);
return new Promise().then(data => {
const payLoad = {
notification: {
title: "Thank You For Signing Up",
body: "Enjoy the best features by becoming a premium user"
}
};
return admin.messaging().sendToDevice(token, payLoad);
}).catch(errs => {
console.error("Error Sending Payload", errs);
});
});
This is the edited code for the full function but somehow I know that I'm doing sth wrong while sending the payload. This is the error I am getting below:
TypeError: Promise resolver undefined is not a function
at exports.sendSignUpNotification.functions.database.ref.onWrite (/user_code/index.js:15:10)
at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:112:27)
at next (native)
at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71
at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:82:36)
at /var/tmp/worker/worker.js:716:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
and to get the token on client side, I have called this method on signup:
mAuth.getCurrentUser().getIdToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
@Override
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
Log.d(TAG, "idToken:\t" + idToken);
HashMap<String, String> usersMap = new HashMap<>();
usersMap.put("name", name);
usersMap.put("userId", userId);
usersMap.put("email", email);
usersMap.put("id_token", idToken);
}
I have saved this token and referenced it in my script for cloud function. Is this the right token or should I use the one from FirebaseInstanceIdService
like below:
@Override
public void onTokenRefresh() {
super.onTokenRefresh();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed Token:\t" + refreshedToken);
}
Thank you.
Upvotes: 1
Views: 3620
Reputation: 317928
You're using the old beta API with the new 1.x version of the SDK. The way that database events work has changed. The changes for the entire SDK are summarized here. onWrite events now take two parameters, a change and a context. The change contains the before and after snapshots, and the context contains the wildcard values.
To get the userId wildcard, you would now say:
exports.sendSignUpNotification = functions.database.ref(`/users/{userId}`).onWrite((change, context) => {
const userId = context.params.userId
Please see the documentation for more current examples.
Also in your code this line has a bug:
let token = admin.database().ref(`/users/{userId}/notificationTokens`).once('value');
The JavaScript syntax for variable interpolation in a backtick delimited string requires a dollar sign:
`/users/${userId}/notificationTokens`
That line has yet another bug. You're not making use of the promise returned by once() to actually get a hold of the value in the database. token
is going to contain that promise, not the contents of the database.
And you're also going to have to return a promise that resolves when all the async work is done in the function, which you're currently not doing.
Upvotes: 1