如何仅在用户下载应用程序后获取设备令牌?

Posted

技术标签:

【中文标题】如何仅在用户下载应用程序后获取设备令牌?【英文标题】:How to get the device token only once the user downloads the application? 【发布时间】:2019-12-21 04:56:38 【问题描述】:

我有一个监听 Firebase 存储的云功能,每当我上传文档时,它都会监听它,并根据文档提供的数据更新 Firestore。

现在,我想在每次上传文档时通知用户,所以我在同一个云功能中添加了推送通知的功能,并创建了一个服务设备令牌,存储在设备集合中,遍历集合并发送通知。

我遇到的问题是,每次打开应用程序时,我的 Firstore 中的写入都会增加 1,我认为它来自通知的错误实现。

我应该只在用户下载应用程序后才写入令牌,但似乎每次初始化应用程序时都会写入令牌。

我可以看到每当应用程序初始化时我都在调用该函数,我尝试使用 if 语句检查令牌是否已经存在,如果存在则不返回任何内容,否则将其写入集合,但它没有t 似乎工作正常。

这是我的代码,请告诉我我做错了什么。

这是我的云功能:

exports.addFile = functions.storage.object().onFinalize(object => 
    if (object && object.name) 


     ........... // perform the initial process

        ).then(() => 
            console.log('Data is stored');
            setTimeout(async () => 
                // SEND NOTIFICATION 
                //NOTIFICATION CONTENT 
                const payLoad = 
                    notification: 
                        title: 'New Cat',
                        body: `Check it out!`,
                        sound: 'Enabled'
                    ,
                
                // COLLECTION REFERENCE
                const colRef = db.collection('Devices');

                // device reference 
             const deviceRef = colRef.where('userId', '==','testUserId');

                // get users tokens and send notification 
                const devices = await deviceRef.get();
                const tokens: any = [];

                //loop over documents 
                devices.forEach(result => 
                    const token = result.data().token;
                    tokens.push(token);
                );
                console.log('tokens', tokens);

                //Send Notifications 
                return admin.messaging().sendToDevice(tokens, 
                 payLoad).then(response => 
                    // check if there is an error for each message 
                    response.results.forEach((result, index) => 
                    const error = result.error;
                      if (error) 
                            console.error('Failure sending notification 
                             to', tokens[index], error);
                        if (error.code === 'messaging/invalid- 
                         registration-token' ||
                          error.code === 'messaging/registration- 
                          token-not-registered') 
                        colRef.doc(tokens[index]).delete().then(() => 
                         console.log(tokens[index], 'have been deleted');
                               ).catch(err => 
                                    console.log(err);
                                )
                            

                        
                    )
                )
            , 5000);

        )
     
   
    return;

);

这是我的通知服务:

  // GET TOKEN
  async getToken() 
    let token;
    if (this.platform.is('android')) 
      token = await this.firebase.getToken();
      console.log('token', token);
    
  if (this.platform.is('ios')) 
     token = await this.firebase.getToken();
     await this.firebase.grantPermission();
   

    this.saveToken(token);
  

 private saveToken(token) 
   if (!token)  return; 

   const devicesRef = this.afs.collection('Devices');

   const data = 
     token,
   ;
   if (token === devicesRef.doc(token)) 
     return;
    else 
     return devicesRef.doc(token).set(data);
   
  

  onNotifications() 
  return this.firebase.onMessageReceived();
 

最后,app.ts 中的代码:

  private async presentToast(message) 
    const toast = await this.toastController.create(
      message,
      duration: 3000
    );
    toast.present();
    
    private notificationSetup() 
    this.nS.getToken();
    this.nS.onNotifications().subscribe(
      (msg) => 
        if (this.platform.is('ios')) 
      this.presentToast(msg.aps.alert);
         else 
          this.presentToast(msg.body);
        
      );
   

initializeApp()
   this.platform.ready().then(() => 
   this.statusBar.styleDefault();
   this.splashScreen.hide();
   this.notificationSetup();
   timer(3000).subscribe(() => 
    this.showSplash = false;
  );
);

【问题讨论】:

【参考方案1】:

我可以在这里找到两件事:

    您希望用户知道您何时上传文件。

    您只想在用户下载应用程序时存储您的令牌,但每次打开应用程序时都会存储它。

我可以帮助解决第一个问题。

这听起来像是您想使用触发器。 Check this other answer,我觉得和你想做的差不多。

【讨论】:

您好,感谢您的回答。我已经想到了第一个,唯一的问题是数字 2。我不确定令牌是否应该写入一次,或者它们是否过期并在每次应用程序初始化时写入。

以上是关于如何仅在用户下载应用程序后获取设备令牌?的主要内容,如果未能解决你的问题,请参考以下文章

如果应用断开互联网,如何再次获取设备令牌(APNS)?

如何获取用户的设备令牌并将其作为 PDF 文件附加到电子邮件中?

应用启动后如何获取 iOS 推送通知令牌

如何在 iPhone 上请求设备令牌

如何作为 Apple 推送通知服务提供商获取设备令牌?

Firebase React Native——如何获取和传输设备 ID/令牌?