Я следую этому примеру в файле node.js, чтобы отправить уведомление в мое мобильное приложение и удалить все токены, которые не используются пользователем, из массива в документе в Firestore. Изначально мой исходный код предполагал, что у каждого пользователя есть только один токен. После нескольких дней ошибок я определил, как управлять несколькими токенами пользователя как в облаке, так и в моем коде Android.
(https://github.com/firebase/functions-samples/blob/master/fcm-notifications/functions/index.js)
Ниже приведен мой исходный код node.js, который я использую для связи с помощью одного токена.
'use-strict'
const functions = require('firebase-functions');
const admin=require('firebase-admin');
admin.initializeApp(functions.config().firebase); fr
exports.sendAcceptFriendRequest=functions.firestore.document("Notifications/{user_id}/Accepted_Friend_Requests/{user_email}").onWrite((change,context)=> {
const user_id=context.params.user_id;
const email_id=context.params.user_email;
console.log("id: "+user_id+" email: "+email_id);
return admin.firestore().collection("Notifications").doc(user_id).collection("Accepted_Friend_Requests").doc(email_id).get().then((queryResult)=>{
//main
const from_user_id=queryResult.data().id;
const from_name=queryResult.data().name;
const from_email=queryResult.data().email;
const from_imagee=queryResult.data().image;
const noti_id=queryResult.data().notification_id;
const timestamp=queryResult.data().timestamp;
const from_data=admin.firestore().collection("Users").doc(from_user_id).get();
const to_data=admin.firestore().collection("Users").doc(user_id).get();
return Promise.all([from_data,to_data]).then(result=>{
const from_image=result[0].data().image;
const from_email=result[0].data().email;
const from_token=result[0].data().token_id;
const payload={
data:{
notification_id:noti_id,
timestamp:timestamp,
friend_id:from_user_id,
friend_name:from_name,
friend_email:from_email,
friend_image:from_imagee,
friend_token:from_token,
title:from_name,
body:"Accepted your friend request",
click_action:"com.app.ej.ms.TARGET_ACCEPTED"
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToDevice(to_token,payload).then(function (results) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message: ", results);
console.log("Error: ", results.results[0].error);
return;
})
.catch(function (error) {
console.log("Error sending message: ", error);
});
});
});
});
Ниже приведен код, приведенный на веб-сайте GitHub в качестве примера того, как управлять просроченными токенами в облаке с использованием базы данных Firebase Realtime .
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
/**
* Triggers when a user gets a new follower and sends a notification.
*
* Followers add a flag to `/followers/{followedUid}/{followerUid}`.
* Users save their device notification tokens to `/users/{followedUid}/notificationTokens/{notificationToken}`.
*/
exports.sendFollowerNotification = functions.database.ref('/followers/{followedUid}/{followerUid}')
.onWrite((change, context) => {
const followerUid = context.params.followerUid;
const followedUid = context.params.followedUid;
// If un-follow we exit the function.
if (!change.after.val()) {
return console.log('User ', followerUid, 'un-followed user', followedUid);
}
console.log('We have a new follower UID:', followerUid, 'for user:', followedUid);
// Get the list of device notification tokens.
const getDeviceTokensPromise = admin.database()
.ref(`/users/${followedUid}/notificationTokens`).once('value');
// Get the follower profile.
const getFollowerProfilePromise = admin.auth().getUser(followerUid);
// The snapshot to the user's tokens.
let tokensSnapshot;
// The array containing all the user's tokens.
let tokens;
return Promise.all([getDeviceTokensPromise, getFollowerProfilePromise]).then(results => {
tokensSnapshot = results[0];
const follower = results[1];
// Check if there are any device tokens.
if (!tokensSnapshot.hasChildren()) {
return console.log('There are no notification tokens to send to.');
}
console.log('There are', tokensSnapshot.numChildren(), 'tokens to send notifications to.');
console.log('Fetched follower profile', follower);
// Notification details.
const payload = {
notification: {
title: 'You have a new follower!',
body: `${follower.displayName} is now following you.`,
icon: follower.photoURL
}
};
// Listing all tokens as an array.
tokens = Object.keys(tokensSnapshot.val());
// Send notifications to all tokens.
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', 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(tokensSnapshot.ref.child(tokens[index]).remove());
}
}
});
return Promise.all(tokensToRemove);
});
});
Ниже мое редактирование моего исходного кода Firestore с использованием функции (как подробно описано в примере GitHub), которая проверяет токены с истекшим сроком действия из массива токенов, а не просто проверяет один токен.
'use-strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendAcceptFriendRequest=functions.firestore.document("Notifications/{user_id}/Accepted_Friend_Requests/{user_email}").onWrite((change,context)=> {
const user_id = context.params.user_id;
const email_id = context.params.user_email;
const db = admin.firestore();
console.log("id: " + user_id + " email: " + email_id);
return db.collection("Notifications").doc(user_id).collection("Accepted_Friend_Requests").doc(email_id).get().then((queryResult)=>{
const from_user_id = queryResult.data().id;
const from_name = queryResult.data().name;
const from_email = queryResult.data().email;
const from_imagee = queryResult.data().image;
const noti_id = queryResult.data().notification_id;
const timestamp = queryResult.data().timestamp;
const from_data = db.collection("Users").doc(from_user_id).get();
const to_data = db.collection("Users").doc(user_id).get();
const device_tokens = queryResult.data().token_ids;
let tokensSnapshot; // The snapshot to the user's tokens.
let tokens; // The array containing all the user's tokens.
// https://howtofirebase.com/promises-for-firebase-bbb9d0d595ed
return Promise.all([from_data, to_data, device_tokens]).then(result=>{
const from_image=result[0].data().image;
const from_email=result[0].data().email;
tokensSnapshot = result[2];
// Listing all tokens as an array.
tokens = Object.keys(tokensSnapshot.val());
const payload={
data:{
notification_id:noti_id,
timestamp:timestamp,
friend_id:from_user_id,
friend_name:from_name,
friend_email:from_email,
friend_image:from_imagee, // string from token gone
title:from_name,
body:"Accepted your friend request",
click_action:"com.app.ej.ms.TARGET_ACCEPTED"
}
};
// Send notifications to all tokens.
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', 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(tokensSnapshot.ref.child(tokens[index]).remove());
}
}
else {
console.log("Successfully sent friend request: ", tokens[index], response);
}
});
return Promise.all(tokensToRemove);
});
});
});
Поскольку я не смог найти эквивалент Firestore для примера GitHub, я хотел бы попросить вас следовать моей логике, если мой файл Firestore node.js действительно эквивалентен и работает, как и ожидалось.
Мой второй вопрос: "tokensToRemove.push (tokensSnapshot.ref.child (tokens [index]). Remove ());" в примере GitHub. Как это переводится в Firestore? Я думал, что это может сработать, но "ref" - это строго База данных в реальном времени, не так ли?
Мой третий вопрос: можно ли в Promise.all иметь три поля?
"Promise.all ([from_data, to_data, device_tokens]). Then (result => {"
Я только когда-либо видел, чтобы он использовался с одним или двумя полями.