I have managed to setup firebase cloud functions to send notification to topics. the problem is that it sends to all users including the sender, how can i setup my cloud fun
From the Docs of firebase, Using topics for sending notifications should be done for notifications that are public and are not time critical. In your case notification is not public and as sender is also subscribed to that particular topic he will also get the notification. therefore if you want to avoid sending notification to sender you have to unsubscribe that sender from your topic.
Or better solution is that you should send the notifications to single devices using there FCM tokens. the node.js code for sending notification for FCM tokens is
admin.messaging().sendToDevice(<array of tokens>, payload);
and you can get the device tokens from onTokenRefresh() method of your android's FirebaseInstanceIdService.
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// TO DO: send token to your server or firebase database
}
Update:
To store the firebase tokens to your database Now you should structure your database like this
-users
|-user1uid
| |-name //your choice
| |-email //your choice
| |-fcmTokens
| |-valueOftoken1:true
| |-valueOftoken2:true
-notes
| |-notesId
| |-yourdata
| |-createdBy:uidofUser //user who created note
|
-subscriptions //when onWrite() will trigger we will use this to get UID of all subscribers of creator of "note".
| |-uidofUser
| |-uidofSubscriber1:true //user subscribe to notes written. by parent node uid
| |-uidofSubscriber2:true
to save the tokens in database here is the code for onTokenRefresh()
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken(); //get refreshed token
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser(); //get currentto get uid
if(user!=null){
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()); // create a reference to userUid in database
if(refreshedToken!=null) //
mDatabase.child("fcmTokens").child(refreshedToken).setValue(true); //creates a new node of user's token and set its value to true.
else
Log.i(TAG, "onTokenRefresh: token was null");
}
Log.d(tag, "Refreshed token SEND TO FIREBASE: " + refreshedToken);
}
when ever new token is created for this user the above code will create new node in fcmTokens of the user.
Here comes the node.js part of retrieving users token and sending notification to those tokens. for this
exports.sendNotesNotification = functions.database.ref('/Notes/{pushId}')
.onWrite(event => {
const notes = event.data.val();
const createdby = notes.createdBy;
const getAllSubscribersPromise = admin.database().ref(`/subscriptions/${createdby}/`).once('value'); // retrieving subscribers
const payload = {
notification: {
username: notes.username,
title: notes.title,
body: notes.desc
}
}
return getAllSubscribersPromise.then(result => {
const userUidSnapShot = result; //results will have children having keys of subscribers uid.
if (!userUidSnapShot.hasChildren()) {
return console.log('There are no subscribed users to write notifications.');
}
console.log('There are', userUidSnapShot.numChildren(), 'users to send notifications to.');
const users = Object.keys(userUidSnapShot.val()); //fetched the keys creating array of subscribed users
var AllFollowersFCMPromises = []; //create new array of promises of TokenList for every subscribed users
for (var i = 0;i<userUidSnapShot.numChildren(); i++) {
const user=users[i];
console.log('getting promise of user uid=',user);
AllFollowersFCMPromises[i]= admin.database().ref(`/users/${user}/fcmToken/`).once('value');
}
return Promise.all(AllFollowersFCMPromises).then(results => {
var tokens = []; // here is created array of tokens now ill add all the fcm tokens of all the user and then send notification to all these.
for(var i in results){
var usersTokenSnapShot=results[i];
console.log('For user = ',i);
if(usersTokenSnapShot.exists()){
if (usersTokenSnapShot.hasChildren()) {
const t= Object.keys(usersTokenSnapShot.val()); //array of all tokens of user [n]
tokens = tokens.concat(t); //adding all tokens of user to token array
console.log('token[s] of user = ',t);
}
else{
}
}
}
console.log('final tokens = ',tokens," notification= ",payload);
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to uid=', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' || error.code === 'messaging/registration-token-not-registered') {
tokensToRemove.push(usersTokenSnapShot.ref.child(tokens[index]).remove());
}
}
else{
console.log("notification sent",result);
}
});
return Promise.all(tokensToRemove);
});
return console.log('final tokens = ',tokens," notification= ",payload);
});
});
});
i have not checked the node.js part let me know if you still have problem.