首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重置推送通知/设备注册/实例Id -通过TestFlight或App进行应用程序更新- Firebase消息传递iOS/ App本机防火墙

重置推送通知/设备注册/实例Id -通过TestFlight或App进行应用程序更新- Firebase消息传递iOS/ App本机防火墙
EN

Stack Overflow用户
提问于 2020-01-18 00:20:37
回答 2查看 4.7K关注 0票数 1

在这个问题上做了大量的研究,首先我的设置是:

我的问题非常简单和直截了当,虽然我似乎无法找到一个明确的方法来解决这个问题。

我部署了我的应用程序的4.2版本。iOS中的()工作得很好。然后,我将4.3部署到TestFlight以开始测试。安装4.3通过TestFlight和FCM停止工作,没有推送通知。如果我删除应用程序,并通过TestFlight推送通知安装4.3再次工作,设备将被注册。

我也可以复制这个问题,更新应用商店最新发布的应用程序的安装版本,这并不奇怪。

我知道InstanceId/device令牌是基于应用程序build+device的,所以当应用程序更新时,令牌更改是有意义的,但是当我从4.2更新到4.3时,令牌是相同的:

代码语言:javascript
运行
复制
const fcmToken = await firebase.messaging().getToken(); //same whether 4.2 or 4.3

是的,firebase.messaging().getToken()在初始创建时被缓存。

所以我很想听听象征性的改变事件:

代码语言:javascript
运行
复制
firebase.messaging().onTokenRefresh(async () => {
  console.log('======onTokenRefresh=========');
  AsyncStorage.removeItem(FCM_TOKEN_KEY);
  await getToken();
});

似乎从未开火。我甚至在我的应用程序中添加了一个按钮,尝试强制使用一个新的InstanceId,并在从TestFlight或AppStore更新版本后向FCM注册,这并没有帮助:

代码语言:javascript
运行
复制
export async function forceRefresh() {
  console.log('================force a new registration!!!==========');
  AsyncStorage.removeItem(FCM_TOKEN_KEY);
  firebase.messaging().deleteToken();
  firebase.iid().deleteToken();
  registerForPushNotificationsAsync(true);
} 

不,不管用。

所以这个故事的寓意是,当我更新我的应用程序的版本,我的客户,谁的推送通知是很好的,将不再注册推送通知,当他们更新他们的应用程序到下一个版本。

可能是我一直在研究的线索:

有趣的是,在应用程序更新开始时,推送通知将停止工作,因为应用程序更新--我看到了两个不同的令牌,也许第一个是苹果APN令牌

代码语言:javascript
运行
复制
2020-01-17 18:48:09.371741-0800 native[4462:1287461] -[RNFirebaseMessaging messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: eBBgznWj1FU:APA91bF8vTmpkwcojp4oDSKFzlPDp6ylEIe_WGNzu24SKHS6RR-3xPu2-cX-Qyc8rrMIQMvkCJftT9711ll1WdshBWS4iEpZ3XpiPeTynqM-nvDjpAUUUWJpfT5aeo6G_scDsN9iipwI
2020-01-17 18:48:09.378382-0800 native[4462:1287621] 6.15.0 - [Firebase/InstanceID][I-IID014012] Invalidating cached token for 255558254149 (*) due to token is no longer fresh.

然后再晚一点,在加载push通知工作的应用程序的前一个版本中,我看到了日志中的工作“默认令牌”:

代码语言:javascript
运行
复制
2020-01-17 18:48:09.987571-0800 native[4462:1287610] 6.15.0 - [Firebase/InstanceID][I-IID014001] Token fetch successful, token: dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B, authorizedEntity: 255558254149, scope:*
2020-01-17 18:48:09.987764-0800 native[4462:1287461] -[RNFirebaseMessaging messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B
2020-01-17 18:48:09.993088-0800 native[4462:1287610] 6.15.0 - [Firebase/InstanceID][I-IID003010] Successfully fetched default token.
2020-01-17 18:48:09.993755-0800 native[4462:1287610] 6.15.0 - [Firebase/InstanceID][I-IID003008] Got default token dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B

有趣的是,在删除当前版本的应用程序并安装最新版本(在以前的日志中是更新版本)之后,我们可以看到相同的过程相反,首先我的当前令牌被找到,并被认为不再新鲜:

代码语言:javascript
运行
复制
messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B
2020-01-17 19:03:06.651179-0800 native[4475:1291698] 6.15.0 - [Firebase/InstanceID][I-IID014012] Invalidating cached token for 255558254149 (*) due to token is no longer fresh.

随后,新令牌被加载,并被视为默认令牌,我的新安装立即收到FCM通知:

代码语言:javascript
运行
复制
2020-01-17 19:03:07.997209-0800 native[4475:1291564] -[RNFirebaseMessaging messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: ebz2ACPpBkg0kGsgs9yF7_:APA91bGErCaPMuLyRk-_BLZXUk8_U6FyxvKHbI0NPgddFWl_-nLZuCc6HbHg8kaLMDJiO7sHFS8THAuV132xgri8uQ9YV4g8zDXJySrKsSTNiDq9HcXpzUQXQlPy8bTaxZ3gyRxyCy3p
2020-01-17 19:03:08.018870-0800 native[4475:1291684] 6.15.0 - [Firebase/InstanceID][I-IID014001] Token fetch successful, token: ebz2ACPpBkg0kGsgs9yF7_:APA91bGErCaPMuLyRk-_BLZXUk8_U6FyxvKHbI0NPgddFWl_-nLZuCc6HbHg8kaLMDJiO7sHFS8THAuV132xgri8uQ9YV4g8zDXJySrKsSTNiDq9HcXpzUQXQlPy8bTaxZ3gyRxyCy3p, authorizedEntity: 255558254149, scope:*
2020-01-17 19:03:08.019018-0800 native[4475:1291684] 6.15.0 - [Firebase/InstanceID][I-IID003010] Successfully fetched default token.
2020-01-17 19:03:08.019065-0800 native[4475:1291684] 6.15.0 - [Firebase/InstanceID][I-IID003008] Got default token ebz2ACPpBkg0kGsgs9yF7_:APA91bGErCaPMuLyRk-_BLZXUk8_U6FyxvKHbI0NPgddFWl_-nLZuCc6HbHg8kaLMDJiO7sHFS8THAuV132xgri8uQ9YV4g8zDXJySrKsSTNiDq9HcXpzUQXQlPy8bTaxZ3gyRxyCy3p

刚刚在日志中找到了这个利息声明:

在检索发件人ID '255558254149‘的FCM令牌之前,APNS设备令牌未设置。此FCM令牌的通知不会在APNS.Be上传递,一旦APNS设备令牌被设置,肯定会重新检索FCM令牌。

很难相信这种情况会持续发生,但似乎确实是这样,任何帮助都将是非常感谢的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-18 06:34:09

最后,我发现了一个很好的提示,这里

似乎使用react本机的Firebase.messaging().getToken()并不总是返回最新的令牌使用onTokenRefresh。我的应用程序是保存和使用一个旧的令牌,而不是更新一个新的-非常小的比赛条件。 只需使用Firebase.messaging.onTokenRefresh()作为真相的来源,以避免迁移应用程序的问题。另外,为了确保您得到了一个有效的令牌。您可能希望在迁移时删除令牌,比如使用v4 ->进行等待Firebase.iid().deleteToken()或v5 (Firebase.messaging().deleteToken() )。然后依靠onTokenRefresh发送一个新的发送到您的服务器。

现在,在上述引文中提到的firebase.messaging().deleteToken()并不“足够好”,当TestFlight或Apple有一个应用更新时,就会产生一个tokenRefresh。

我不得不调用异步(当涉及到这个问题时,一切都是异步的,这是经验法则):

代码语言:javascript
运行
复制
firebase.iid().delete();

这个React Native Firebase api方法删除了InstanceId,这是用于令牌的真正用途。

这将触发onTokenRefresh。因此,我所做的是检查应用程序的版本和构建号,并将其存储在应用程序用户数据(NSDefaults for iOS)中,检查该版本和构建是否存在,如果它没有“刷新”设备令牌。这样只会发生一次。

我将添加我的代码,希望它能帮助其他人解决这个问题,从本质上说,从我的研究来看,使用5.x --这是通过iOS应用程序更新使用Firebase消息来维护无缝推送通知注册的方法:

在App.js中添加以下内容:

代码语言:javascript
运行
复制
   configureFirebaseCloudMessaging = async () => {
    //wire up Firebase Cloud Messaging onTokenRefresh listener

    this.fcmOnTokenRefreshUnsubscribe = await firebase.messaging().onTokenRefresh(async fcmToken => {
      console.log('*********************** onTokenRefresh *****************');
      //this is callBack called typically sometime in the future but can be call with app loaded but user not logged in
      //check for that case and exit if there is no accessToken to call APIs
      const accessToken = await AsyncStorage.getItem('access-token');
      if (!accessToken) {
        console.log('************** user is not logged in exit onTokenRefresh do not register device ************');
        return;
      }
      await this.registerDevice(fcmToken, BASE_URL);
      await AsyncStorage.setItem('fcmToken', fcmToken);
      firebase.crashlytics().log(`flushed new fcmToken: ${fcmToken}`);
      console.log('***************** success  account updated with latest token **************');
    });

    //Firebase Cloud Messaging time
    await this.requestPushPermission();
    await this.checkFlushv();
  }

  checkFlushv = async () => {
    let FLUSHV = `${DeviceInfo.getVersion()}-build-${DeviceInfo.getBuildNumber()}`;

    const flush = await AsyncStorage.getItem(FLUSHV);
    console.log('======= checking FLUSHV=========', flush);
    if (flush) {
      console.log('***** device token already been flushed ******');
      return;
    }

    const accessToken = await AsyncStorage.getItem('access-token');
    console.log('flushy access token:', accessToken);
    if (!accessToken) {
      console.log('******** user is not logged in do not flush ************');
      return;
    }

    //force push notifications, this will fire onTokenRefresh callback
    await firebase.iid().delete();

    //iterate all keys and remove other builds to keep tidy and TestFlighters possibly going up and back down build versions for testing
    const keys = await AsyncStorage.getAllKeys();
    const buildKeys = keys.filter(key => {
      return key.indexOf('build') !== -1;
    });
    await AsyncStorage.multiRemove(buildKeys);

    //add current build key so no more flushy
    await AsyncStorage.setItem(FLUSHV, FLUSHV);
    console.log(`=================FLUSHV clear: ${FLUSHV}===================`)
  }

  registerDevice = async (token, baseUrl) => {
    console.log(`******** registerDevice token: ${token}, baseUrl: ${baseUrl}`);
    let data = {
      device: 'firebase',
      token: token
    }

    //register token with  account
    axios.post(`${baseUrl}/myapi/register_device`, data)
      .then(response => {
        return {}
      })
      .catch(err => {
        console.log(err)
        return {}
      })
  }

然后在你的App.js中:

代码语言:javascript
运行
复制
  async componentDidUpdate() {
    //a new version of the app could be loaded post/after App.componentDidMount
    await this.checkFlushv();
  }

  async componentWillUnmount() {
    console.log('app componentWillUnmount');
    this.fcmOnTokenRefreshUnsubscribe(); //not really sure unsubcribe is needed but keeping tidy
    this.fcmOnTokenRefreshUnsubscribe = null;
  }

  async componentDidMount() {
    await this.configureFirebaseCloudMessaging();
  }
票数 5
EN

Stack Overflow用户

发布于 2020-02-28 14:30:21

在找到解决方案之前我花了很多时间。

因此,如果在firebase.iid().delete()中调用iOS,则需要在APN中注册新令牌。我在本机firebase文档中没有看到这种情况,只是在lib的类型中找到了

代码语言:javascript
运行
复制
await firebase.messaging().ios.registerForRemoteNotifications()

请在生成新令牌后调用此方法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59796431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档