Firebase云消息传递sendToDevice可以正常工作,但对于相同的令牌列表,sendMulticast失败 [英] Firebase cloud messaging sendToDevice works properly but sendMulticast fails for the same list of tokens

查看:67
本文介绍了Firebase云消息传递sendToDevice可以正常工作,但对于相同的令牌列表,sendMulticast失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于某些类型的消息,我想通过FIRTokens vs主题来定位用户,这些信息存储在我的实时数据库中.我使用 async/await 加载了这些令牌,然后决定是否要将通知发送到某个主题,而不是较小的用户列表.数据加载代码按预期工作.但是奇怪的是,如果我使用 .sendMulticast(payload),则列表中所有令牌的通知都会失败.另一方面,如果我使用 .sendToDevice(adminFIRTokens,有效负载),则通知将成功发送给我的所有用户.现在,我的列表有2个令牌,使用 sendMulticast 我有2个失败,使用 sendToDevice 我有2个成功.我是否错过了 sendMulticast 应该做什么的要点?根据文档:将消息发送至多个设备:

For certain types of messages, I want to target users by FIRTokens vs topic, which are stored in my real-time database. I load these tokens with async/await and then decide if I want to send notifications to a topic vs a smaller list of users. The data loading code works as expected. But what's odd is that if I use .sendMulticast(payload), the notifications fail for all tokens in the list. On the other hand if I use .sendToDevice(adminFIRTokens, payload) the notification goes successfully to all my users. Right now my list has 2 tokens and with sendMulticast I have 2 failures and with sendToDevice I have 2 successes. Am I missing the point of what sendMulticast is supposed to do? According to the docs: Send messages to multiple devices:

REST API和Admin FCM API允许您将消息多播到设备注册令牌列表.每次调用最多可以指定500个设备注册令牌.

The REST API and the Admin FCM APIs allow you to multicast a message to a list of device registration tokens. You can specify up to 500 device registration tokens per invocation.

因此两者在逻辑上都应该起作用.那为什么一个失败而另一个起作用呢?实际上,通过 sendToDevice 我在响应中得到了 multicastId

So both should logically work. Then why does one fail and the other work? In fact with sendToDevice I get a multicastId in the response!

以下是一些控制台输出:

Here are some console outputs:

  1. sendToDevice:

Sent filtered message notification successfully: 
{ 
  results: 
    [ 
      { messageId: '0:1...45' }, 
      { messageId: '16...55' } 
    ], 
    canonicalRegistrationTokenCount: 0, 
    failureCount: 0, 
    successCount: 2, 
    multicastId: 3008...7000 
} 

  1. sendMulticast:

List of tokens that caused failures: dJP03n-RC_Y:...MvPkTbuV,fDo1S8jPbCM:...2YETyXef 

云功能发送通知:

functions.database
  .ref("/discussionMessages/{autoId}/")
  .onCreate(async (snapshot, context) => {
    // console.log("Snapshot: ", snapshot);

    try {
      const groupsRef = admin.database().ref("people/groups");
      const adminUsersRef = groupsRef.child("admin");
      const filteredUsersRef = groupsRef.child("filtered");
      const filteredUsersSnapshot = await filteredUsersRef.once("value");
      const adminUsersSnapshot = await adminUsersRef.once("value");
      var adminUsersFIRTokens = {};
      var filteredUsersFIRTokens = {};

      if (filteredUsersSnapshot.exists()) {
        filteredUsersFIRTokens = filteredUsersSnapshot.val();
      }
      if (adminUsersSnapshot.exists()) {
        adminUsersFIRTokens = adminUsersSnapshot.val();
      }

      const topicName = "SpeechDrillDiscussions";
      const message = snapshot.val();
      const senderName = message.userName;
      const senderCountry = message.userCountryEmoji;
      const title = senderName + " " + senderCountry;
      const messageText = message.message;
      const messageTimestamp = message.messageTimestamp.toString();
      const messageID = message.hasOwnProperty("messageID")
        ? message.messageID
        : undefined;
      const senderEmailId = message.userEmailAddress;
      const senderUserName = getUserNameFromEmail(senderEmailId);

      const isSenderFiltered = filteredUsersFIRTokens.hasOwnProperty(
        senderUserName
      );

      var payload = {
        notification: {
          title: title,
          body: messageText,
          sound: "default",
        },
        data: {
          messageID: messageID,
          messageTimestamp: messageTimestamp,
        },
      };

      if (isSenderFiltered) {
        adminFIRTokens = Object.values(adminUsersFIRTokens);
        // payload.tokens = adminFIRTokens; //Needed for sendMulticast
        return (
          admin
            .messaging()
            .sendToDevice(adminFIRTokens, payload)
            // .sendMulticast(payload)
            .then(function (response) {
              if (response.failureCount === 0) {
                console.log(
                  "Sent filtered message notification successfully:",
                  response
                );
              } else {
                console.log(
                  "Sending filtered message notification failed for some tokens:",
                  response
                );
              }
              // if (response.failureCount > 0) {
              //   const failedTokens = [];
              //   response.responses.forEach((resp, idx) => {
              //     if (!resp.success) {
              //       failedTokens.push(adminFIRTokens[idx]);
              //     }
              //   });
              //   console.log(
              //     "List of tokens that caused failures: " + failedTokens
              //   );
              // }

              return true;
            })
        );
      } else {
        payload.topic = topicName;
        return admin
          .messaging()
          .send(payload)
          .then(function (response) {
            console.log("Notification sent successfully:", response);
            return true;
          });
      }
    } catch (error) {
      console.log("Notification sent failed:", error);
      return false;
    }
  });

推荐答案

我认为这是使用其他有效负载结构的问题.

I think it's an issue of using a different payload structure.

这是旧版本(没有iOS特定信息):

This is the old one (without iOS specific info):

var payload = {
    notification: {
      title: title,
      body: messageText,
      sound: "default",
    },
    data: {
      messageID: messageID,
      messageTimestamp: messageTimestamp,
    },
  };

这是新版本(apns具有iOS特定信息)

Whereas this is the new version (apns has iOS specific info)

var payload = {
    notification: {
      title: title,
      body: messageText,
    },
    data: {
      messageID: messageID,
      messageTimestamp: messageTimestamp,
    },
    apns: {
      payload: {
        aps: {
          sound: "default",
        },
      },
    },
  };

使用新结构, send sendMulticast 都可以正常工作.有效负载中不支持发送失败或出现诸如apns密钥之类的错误.

With the new structure, both send and sendMulticast are working properly. Which would fail to send or give errors like apns key is not supported in payload.

新功能:

functions.database
  .ref("/discussionMessages/{autoId}/")
  .onCreate(async (snapshot, context) => {
    // console.log("Snapshot: ", snapshot);

    try {
      const groupsRef = admin.database().ref("people/groups");
      const adminUsersRef = groupsRef.child("admin");
      const filteredUsersRef = groupsRef.child("filtered");
      const filteredUsersSnapshot = await filteredUsersRef.once("value");
      const adminUsersSnapshot = await adminUsersRef.once("value");
      var adminUsersFIRTokens = {};
      var filteredUsersFIRTokens = {};

      if (filteredUsersSnapshot.exists()) {
        filteredUsersFIRTokens = filteredUsersSnapshot.val();
      }
      if (adminUsersSnapshot.exists()) {
        adminUsersFIRTokens = adminUsersSnapshot.val();
      }

      // console.log(
      //   "Admin and Filtered Users: ",
      //   adminUsersFIRTokens,
      //   " ",
      //   filteredUsersFIRTokens
      // );

      const topicName = "SpeechDrillDiscussions";
      const message = snapshot.val();

      // console.log("Received new message: ", message);

      const senderName = message.userName;
      const senderCountry = message.userCountryEmoji;
      const title = senderName + " " + senderCountry;
      const messageText = message.message;
      const messageTimestamp = message.messageTimestamp.toString();
      const messageID = message.hasOwnProperty("messageID")
        ? message.messageID
        : undefined;
      const senderEmailId = message.userEmailAddress;
      const senderUserName = getUserNameFromEmail(senderEmailId);

      const isSenderFiltered = filteredUsersFIRTokens.hasOwnProperty(
        senderUserName
      );

      console.log(
        "Will attempt to send notification for message with message id: ",
        messageID
      );

      var payload = {
        notification: {
          title: title,
          body: messageText,
        },
        data: {
          messageID: messageID,
          messageTimestamp: messageTimestamp,
        },
        apns: {
          payload: {
            aps: {
              sound: "default",
            },
          },
        },
      };
      console.log("Is sender filtered? ", isSenderFiltered);

      if (isSenderFiltered) {
        adminFIRTokens = Object.values(adminUsersFIRTokens);
        console.log("Sending filtered notification with sendMulticast()");
        payload.tokens = adminFIRTokens; //Needed for sendMulticast
        return admin
          .messaging()
          .sendMulticast(payload)
          .then((response) => {
            console.log(
              "Sent filtered message (using sendMulticast) notification: ",
              JSON.stringify(response)
            );
            if (response.failureCount > 0) {
              const failedTokens = [];
              response.responses.forEach((resp, idx) => {
                if (!resp.success) {
                  failedTokens.push(adminFIRTokens[idx]);
                }
              });
              console.log(
                "List of tokens that caused failures: " + failedTokens
              );
            }
            return true;
          });
      } else {
        console.log("Sending topic message with send()");
        payload.topic = topicName;
        return admin
          .messaging()
          .send(payload)
          .then((response) => {
            console.log(
              "Sent topic message (using send) notification: ",
              JSON.stringify(response)
            );
            return true;
          });
      }
    } catch (error) {
      console.log("Notification sent failed:", error);
      return false;
    }
  });

这篇关于Firebase云消息传递sendToDevice可以正常工作,但对于相同的令牌列表,sendMulticast失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆