android - Firebase 函数接收对象而不是字符串

标签 android firebase firebase-realtime-database firebase-cloud-messaging

请耐心等待。我花了一个月的时间来解决这个问题:我已经使用 Firebase 数据库和 Firebase 函数大约一年了。我已经让它工作了……但前提是我将消息文本作为字符串发送。问题是现在我希望收到一个 OBJECT,但我不确定如何在 FireBaseMessage 中执行此操作。

我以前的结构:

messages
   T9Vh5cvUcbqC8IEZowBpJC3
      ZWfn7876876ZGJeSNBbCpPmkm1
           message



"messages": {
        ".read": true,
      "$receiverUid": {
        "$senderUid": {
          "$message": {
            ".read": true,
            ".write": "auth.uid === $senderUid"

我对听众的功能是这样的:

exports.sendMessage = functions.database.ref('/messages/{receiverUid}/{senderUid}/{message}')

这是有问题的...出于各种原因。也就是说,如果旧消息是“嘿”,然后同一个人又写了“嘿”……那么原始消息就会被覆盖。

所以我的新结构更像这样:

messages
  -LkVcYqJoEroWpkXZnqr
      body: "genius grant"
      createdat: 1563915599253
      name: "hatemustdie"
      receiverUid: "TW8289372984KJjkhdsjkhad"
      senderUid: "yBNbs9823789KJkjahsdjkas"

写成:

mDatabase.child("messages").push().setValue(message);

...我只是不确定如何写出该函数。

我的意思是……理想情况下……应该是这样的:

exports.sendMessage = functions.database.ref('/messages/{receiverUid}/{senderUid}/{msgID}/{msgOBJECT}')

...但我只是不确定 Firebase 函数如何读取这个新结构。

现在我像这样推送到数据库:

mDatabase.child("messages").child(guid).child(user_Id).push().setValue(msgObject).addOnSuccessListener(this, new OnSuccessListener<Void>() {
                                @Override
                                public void onSuccess(@NonNull Void T) {
                                    Log.d("MessageActivity", "Message Sent");

基本上我只想接收消息对象......其中包含所有内容......当它从通知到达时......并且能够轻松解析正文,日期,用户标识等。

有人可以解释一下正确的方法吗?

更新 根据要求,这里是完整的云功能:

exports.sendMessage = functions.database.ref('/messages/{receiverUid}/{senderUid}/{msgId}/{message}')
    .onWrite(async (change, context) => {
      const message = context.params.message;
      // const messageId = context.params.messageId;
      const receiverUid = context.params.receiverUid;
      const senderUid = context.params.senderUid;
      // If un-follow we exit the function.
      if (!change.after.val()) {
        return console.log('Sender ', senderUid, 'receiver ', receiverUid, 'message ', message);
      }
      console.log('We have a new message: ', message, 'for: ', receiverUid);

      // Get the list of device notification tokens.
      const getDeviceTokensPromise = admin.database()
          .ref(`/users/${receiverUid}/notificationTokens`).once('value');

      // Get the follower profile.
      const getSenderProfilePromise = admin.auth().getUser(senderUid);

      // The snapshot to the user's tokens.
      let tokensSnapshot;

      // The array containing all the user's tokens.
      let tokens;

      const results = await Promise.all([getDeviceTokensPromise, getSenderProfilePromise]);
      tokensSnapshot = results[0];
      const sender = 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 sender profile', sender);
//        console.log('David you're looking for the following UID:', followerUid);

        // Notification details.
        const payload = {
          notification: {
            title: `${sender.displayName} sent you a message.`,
            body: message,
            tag: senderUid
          },
        //  'data': { 'fuid': followerUid }
          data: { 
            type: 'message', 
            name: sender.displayName
          }
        };
      console.log('David you are looking for the following message:', message);
        // Listing all tokens as an array.
      tokens = Object.keys(tokensSnapshot.val());
      // Send notifications to all tokens.
      const response = await admin.messaging().sendToDevice(tokens, payload);
      // 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);
  });

最佳答案

由于您现在将发送者和接收者的 UID 存储在消息中,因此您的 Cloud Functions 函数的声明将需要更改。

取而代之的是:

exports.sendMessage = functions.database.ref('/messages/{receiverUid}/{senderUid}/{msgId}/{message}').onWrite(async (change, context) => {

您需要触发:

exports.sendMessage = functions.database.ref('/messages/{messageId}').onWrite(async (change, context) => {

因此,通过此更改,您的代码将触发写入 /messages 的每条消息。

现在您“只”需要获取发送方和接收方的 UID。由于您不再可以从 context 中获取它们,因此您将改为从 change 中获取它们。具体来说,change.after 包含写入完成后 数据库中存在的数据快照。所以(只要您不删除数据),您可以通过以下方式获取 UID:

const receiverUid = change.after.val().receiverUid;
const senderUid = change.after.val().senderUid;

当然,您还会从那里获得实际消息:

const message = change.after.val().message;

以防万一您需要消息 ID(它在数据库中写入的 -L... 键):

const messageId = change.after.val().messageId;

关于android - Firebase 函数接收对象而不是字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57915970/

相关文章:

java - 如果我知道 jArray 中包含的字符串,如何在 jArray 中找到另一个元素?

javascript - Angularfire:从 $FirebaseObject 的子级创建 $FirebaseObject

ios - 从 Firebase 检索数据

android - 嵌套 fragment 和后栈

java - 是否可以将 Android 包导入普通的 Java 代码

android - 在 fragment 容器上调用 FragmentTransaction.replace() 时会发生什么?

javascript - Firebase Cloud Messaging 的 getToken() 仅在我省略 usePublicVapidKey 方法时才有效,为什么?

firebase - Firestore 规则、原子写入和写入限制

ios - Firebase查询WHERE

android - 可以将 child 批量添加到 Firebase ref,每个 child 都有自己的优先级吗?