重置推送通知/设备注册/实例ID-通过TestFlight或App Store更新应用-Firebase Cloud Messaging iOS / React Native Firebase

布赖恩·奥格登

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

我的问题非常简单直接,尽管我似乎无法找到解决问题的明确方法。

我部署了应用程序的4.2版本。iOS中的Firebase Cloud Messaging(FCM)只是花哨的。然后,我将4.3部署到TestFlight以开始测试。通过TestFlight和FCM安装的4.3停止工作,没有推送通知。如果我删除该应用程序并通过TestFlight推送通知安装4.3,则通知工作再次生效,则该设备已注册。

我还可以重现此问题,从最新发布的App Store更新我的应用程序的安装版本,这并不奇怪。

我知道InstanceId /设备令牌基于应用程序的构建+设备,因此在应用程序更新时令牌会发生变化,但是当我从4.2更新到4.3时我的令牌是相同的:

const fcmToken = await firebase.messaging().getToken(); //same whether 4.2 or 4.3

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

因此,我连线收听令牌更改事件:

firebase.messaging().onTokenRefresh(async () => {
  console.log('======onTokenRefresh=========');
  AsyncStorage.removeItem(FCM_TOKEN_KEY);
  await getToken();
});

这似乎从来没有触发过。我什至在我的应用程序中添加了一个按钮,以在从TestFlight或AppStore更新版本后,尝试强制使用新的InstanceId并向FCM注册,这无济于事:

export async function forceRefresh() {
  console.log('================force a new registration!!!==========');
  AsyncStorage.removeItem(FCM_TOKEN_KEY);
  firebase.messaging().deleteToken();
  firebase.iid().deleteToken();
  registerForPushNotificationsAsync(true);
} 

不,不行。

因此,故事的寓意是,当我更新应用程序的版本时,其推送通知正在正常运行的客户在将其应用程序更新到下一个版本时将不再为推送通知注册。

我可能正在研究的参考资料可能是线索:

关于应用程序更新开始的有趣之处在于,由于应用程序更新,推送通知将停止工作,我看到了两个不同的令牌,也许第一个是AppleAPN令牌

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.

然后再从加载了推送通知的应用程序的先前版本中获取我之前的令牌,然后在日志中看到“默认令牌”工作:

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

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

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通知:

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设备令牌。不会通过APNS传递对此FCM令牌的通知。一旦设置了APNS设备令牌,请确保重新检索FCM令牌。

很难相信这种情况一直如此发生,但是确实如此,任何帮助将不胜感激。

布赖恩·奥格登

好吧,这最终成为了比赛条件,我在这里找到了一个很好的提示

似乎带有react-native-firebase Firebase.messaging()。getToken()不会总是返回最新的令牌-而是使用onTokenRefresh。我的应用正在保存并使用旧令牌,而不是更新新令牌-竞争条件很小。

只需将Firebase.messaging.onTokenRefresh()用作事实来源,即可避免迁移应用程序时出现问题。另外,请确保您获得了有效的令牌。您可能想要在迁移时使用v4-> await Firebase.iid()。deleteToken()或v5(Firebase.messaging()。deleteToken()。)上的令牌删除,然后依靠TokenRefresh向您发送新的令牌发送到您的服务器。

现在,firebase.messaging().deleteToken()在上面引述中提到的“足够好”不足以导致从TestFlight或Apple App Store更新应用程序时导致令牌刷新。

我不得不调用异步方法(涉及此问题的一切都是异步方法):

firebase.iid().delete();

React Native Firebaseapi方法会删除InstanceId,这实际上是Firebase Cloud Messaging(FCM)用于令牌的内容。

这将触发onTokenRefresh。因此,我要做的是检查应用程序的版本和内部版本号,并将其存储在应用程序用户数据(iOS的NSDefaults)中,检查该版本和内部版本是否存在,如果不“刷新”设备令牌。这样,这种情况只会发生一次。

我将添加我的代码,以希望它可以帮助其他人解决此问题,本质上,是从我的研究中开始,使用React Native Firebase 5.x,这是在iOS应用程序中使用Firebase Cloud Messaging维护无缝推送通知注册所要做的更新:

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

   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中:

  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();
  }

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档