繁体   English   中英

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

[英]Detect whether React Native iOS app was opened via push notification

检测应用程序是否通过推送通知启动/打开,描述了如何通过用户点击推送通知来检测本机iOS应用程序是否已打开(即启动或仅启动)。

我如何在React Native中做同样的事情? PushNotificationIOS允许我附加通知监听器...

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

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

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

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

  1. 该应用程序已被完全终止(例如,通过重新启动手机,或者通过双攻的家,然后滑动它关闭在后台运行的应用程序的列表),并正在由用户的水龙头上推送通知启动 这可以通过React.PushNotificationIOS.getInitialNotification方法检测(并获取通知的数据)。
  2. 应用程序已被暂停,并且用户点击推送通知后再次激活该应用程序。 就像在本机应用程序中一样 ,您可以判断这种情况正在发生,因为iOS在打开时将点击通知传递给您的应用程序(即使它是旧通知)并导致您的应用程序处于UIApplicationStateInactive状态时触发通知处理程序(或'background'状态,如React Native的AppStateIOS类所调用的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;
  }
});

对于本地通知

getInitialNotification不适用于本地通知。

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

正因为如此,你需要捕捉推送通知的launchOptionAppDelegate.m并把它传递到本地做出反应作为appProperty

以下是从冷启动后台/非活动状态接收本地推送通知所需的全部内容。

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 repo上创建了一个问题 ,以引起对它的注意,并希望纠正它。 如果您正在处理此问题,请转到此处并竖起大拇指,使其渗透到顶部。

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

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

我发现,该处理程序PushNotificationIOS的处理程序之前,火灾AppStateIOS这是什么意思是,如果我坚持前台/后台状态记忆/ AsyncStorage,我可以检查它像这样在PushNotification事件处理程序: if (activity === 'background')如果那是真的那么我知道我刚从推送通知中打开了应用程序。

我总是在内存和磁盘上保存AppStateIOS前台/后台活动(分别使用redux和redux-persist),所以我只需要在需要知道的时候检查。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM