首页 文章

检测是否通过推送通知打开了React Native iOS应用程序

提问于
浏览
13

Detect if the app was launched/opened from a push notification描述了如何通过用户点击推送通知来检测本机iOS应用程序是否已打开(即启动或仅启动) .

我如何在React Native中做同样的事情? PushNotificationIOS让我附上一个通知听众......

PushNotificationIOS.addEventListener('notification', function (notification) {
    console.log('got a notification', notification);
});

但是当应用程序在前台收到推送通知时,以及当我通过推送通知打开应用程序时,这都会触发 .

如何特别检测第二种情况?

3 回答

  • 34

    这里有两种情况需要以不同的方式检测:

    • 该应用程序已完全终止(例如,通过重新启动手机,或通过双击主页并将其从背景中运行的应用程序列表中删除)并通过React.PushNotificationIOS.getInitialNotification方法由用户's tap on a push notification. This can be detected (and the notification'获取的数据启动 .

    • 该应用已被暂停,并且用户点击推送通知后再次激活该应用 . 只是like in a native app,你可以知道这种情况正在发生,因为iOS在打开时将点击通知传递给你的应用程序(即使它是一个旧通知)并导致你的通知处理程序在你的应用程序处于 UIApplicationStateInactive 状态(或 'background' 状态,正如React Native的AppStateIOS类所称的那样) .

    用于处理这两种情况的代码(您可以将其放在 index.ios.js 或其他在app启动时运行的地方):

    import React from 'react';
    import { PushNotificationIOS, AppState } from 'react-native';
    
    function appOpenedByNotificationTap(notification) {
      // This is your handler. The tapped notification gets passed in here.
      // Do whatever you like with it.
      console.log(notification);
    }
    
    PushNotificationIOS.getInitialNotification().then(function (notification) {
      if (notification != null) {
        appOpenedByNotificationTap(notification);
      }
    });
    
    let backgroundNotification;
    
    PushNotificationIOS.addEventListener('notification', function (notification) {
      if (AppState.currentState === 'background') {
        backgroundNotification = notification;
      }
    });
    
    AppState.addEventListener('change', function (new_state) {
      if (new_state === 'active' && backgroundNotification != null) {
        appOpenedByNotificationTap(backgroundNotification);
        backgroundNotification = null;
      }
    });
    
  • 8

    对于本地通知

    getInitialNotification不适用于本地通知 .

    不幸的是,从React Native的0.28开始,使用 PushNotificationIOS.getInitialNotification() 总是在通过本地推送通知启动时返回 null 值 .

    因此,您需要在 AppDelegate.m 中将推送通知作为 launchOption 捕获,并将其作为 appProperty 传递给React Native .

    以下是从背景/非活动状态冷启动 or 接收本地推送通知所需的全部内容 .

    AppDelegate.m (原生iOS代码)

    // Inside of your didFinishLaunchingWithOptions method...
    
    // Create a Mutable Dictionary to hold the appProperties to pass to React Native.
    NSMutableDictionary *appProperties = [NSMutableDictionary dictionary];
    
    if (launchOptions != nil) {
      // Get Local Notification used to launch application.
      UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    
      if (notification) {
        // Instead of passing the entire Notification, we'll pass the userInfo,
        // where a Record ID could be stored, for example.
        NSDictionary *notificationUserInfo = [notification userInfo];
    
        [ appProperties setObject:notificationUserInfo  forKey:@"initialNotificationUserInfo" ];
      }
    }
    
    // Your RCTRootView stuff...
    
    rootView.appProperties = appProperties;
    

    index.ios.js (React Native)

    componentDidMount() {
      if (this.props.initialNotificationUserInfo) {
        console.log("Launched from Notification from Cold State");
        // This is where you could get a Record ID from this.props.initialNotificationUserInfo
        // and redirect to the appropriate page, for example.
      }
    
      PushNotificationIOS.addEventListener('localNotification', this._onLocalNotification);
    }
    
    componentWillUnmount() {
      PushNotificationIOS.removeEventListener('localNotification', this._onLocalNotification);
    }
    
    _onLocalNotification( notification ) {
      if (AppState.currentState != 'active') {
        console.log("Launched from Notification from Background or Inactive state.");
      }
      else {
        console.log("Not Launched from Notification");
      }
    }
    

    确保从 react-native 导入 PushNotificationIOSAppState .

    我还没有使用远程推送通知进行测试 . 也许@MarkAmery的方法可以很好地使用远程推送通知,但不幸的是,从React Native的当前状态来看,这是我能够从冷状态工作获得本地推送通知的唯一方法 .

    这在React Native中是高度无证的,所以我在他们的GitHub回购中创建了an issue以引起对它的注意并希望纠正它 . 如果您正在处理此问题,请转到此处并竖起大拇指,使其渗透到顶部 .

    https://github.com/facebook/react-native/issues/8580

  • 0

    我找到的解决方案有点hacky并且依赖于我注意到的关于事件处理程序触发的顺序的一些可能奇怪的行为 . 我一直在努力的应用程序需要相同的功能,以便在我通过推送通知打开应用程序时进行具体检测 .

    我发现 PushNotificationIOS 的处理程序在 AppStateIOS 的处理程序之前触发了这意味着,如果我将前台/后台状态保存到内存/ AsyncStorage,我可以在PushNotification事件处理程序中检查它: if (activity === 'background') 并且如果那是真的然后我知道我刚从推送通知中打开了应用程序 .

    我总是将 AppStateIOS 前景/后台活动保存在内存和磁盘上(分别使用redux和redux-persist),所以每当我需要知道时我都会检查它 .

    对于您的目的而言,这可能过于苛刻,并且该行为可能在将来发生变化,或者可能仅仅局限于我 . 尝试查看该解决方案,看看你的想法 .

相关问题