代码之家  ›  专栏  ›  技术社区  ›  Andromeda

FireBase Cloud函数出现CanonicalRegistrationTokenCount错误

  •  0
  • Andromeda  · 技术社区  · 6 年前

    注册后,用户已保存在数据库中,我正在尝试向我的应用发送注册通知。为此,我正在使用firebase云函数。

    我已经从firebaseInstanceIdservice获得了设备令牌,并将其保存在用户的数据库中,路径为 users/userid/deviceToken 并在函数中引用此路径,如下代码所示:

    exports.sendNotification = functions.database.ref("users/{userId}/{instanceId_token}")
    

    我试过将设备记录下来,只是为了确定,但在云控制台中,我一直在获取该日志的其他属性,如: sendNotification deviceToken name , sendNotification deviceToken userId 而不是保存在数据库中的字母数字值。这条路错了吗?

    这是我的全部代码:

    const functions = require('firebase-functions');
    const admin = require('firebase-admin');
    admin.initializeApp(functions.config().firebase);
    
    exports.sendNotification = 
    functions.database.ref("users/{userId}/{instanceId_token}")
        .onWrite((changes, context) => {
        const userId = context.params.userId;
        console.log("user-id", userId);
        const notificationToken = context.params.instanceId_token;
        console.log("deviceToken", notificationToken);
    
        var payload = {
          data: {
              title: "Welcome to My Group",
              message: "You may have new messages"
          }
        };
      return admin.messaging().sendToDevice(notificationToken, payload)
          .then(function (response) {
              return console.log("Successfully sent message: ", response);
          })
          .catch(function (error) {
             return console.log("Error sending message: ", error);
          })
      });
    

    此外,函数在 admin.messaging 回拨:

    Successfully sent message:  { results: [ { error: [Object] } ],
       canonicalRegistrationTokenCount: 0,
       failureCount: 1,
       successCount: 0,
       multicastId: 8880906162831350000 }
    

    如何解决这个问题,我使用的是Android客户端?

    这是我的数据库结构: enter image description here

    1 回复  |  直到 6 年前
        1
  •  1
  •   Renaud Tarnec    6 年前

    您应该在上面的节点上触发函数,如下所示。并访问 instanceId_token 通过 changes.after.val() .

    const functions = require('firebase-functions');
    const admin = require('firebase-admin');
    admin.initializeApp(functions.config().firebase);
    
    exports.sendNotification = 
    functions.database.ref("users/{userId}")
        .onWrite((changes, context) => {
        const userId = context.params.userId;
        console.log("user-id", userId);
        const notificationToken = changes.after.val().instanceId_token;
        console.log("deviceToken", notificationToken);
    
    
    
        var payload = {
          data: {
              title: "Welcome to My Group",
              message: "You may have new messages"
          }
        };
    
      return admin.messaging().sendToDevice(notificationToken, payload)
          .catch(function (error) {
             console.log("Error sending message: ", error);
          })
      });
    

    如果你加上 instanceid_令牌 只有在创建了用户之后,才应该使用 onUpdate() (它“在数据更新时触发”,而 onWrite() “创建、更新或删除数据时触发”)。

    const functions = require('firebase-functions');
    const admin = require('firebase-admin');
    admin.initializeApp(functions.config().firebase);
    
    exports.sendNotification = 
    functions.database.ref("users/{userId}")
        .onUpdate((changes, context) => {
        const userId = context.params.userId;
        console.log("user-id", userId);
        const notificationToken = changes.after.val().instanceId_token;
        console.log("deviceToken", notificationToken);
    
        if (notificationToken === undefined) {
            console.log("notificationToken === undefined");
          return false;
        } else {
    
           var payload = {
              data: {
                 title: "Welcome to My Group",
                 message: "You may have new messages"
             }
           };
          return admin.messaging().sendToDevice(notificationToken, payload)
             .catch(function (error) {
                 console.log("Error sending message: ", error);
             })    
           }
      });
    

    还要注意你不应该这样做

      return admin.messaging().sendToDevice(notificationToken, payload)
          .then(function (response) {
              return console.log("Successfully sent message: ", response);
          })
          .catch(function (error) {
             return console.log("Error sending message: ", error);
          });
    

    因为在这种情况下,您不会返回“在函数中完成所有异步工作时解决”的承诺。(见答案) question )

    所以只要把SendtoDevice的承诺还给我就行了(参见 doc ),如下所示:

      return admin.messaging().sendToDevice(notificationToken, payload)
          .catch(function (error) {
             console.log("Error sending message: ", error);  // here no return
          });