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);
});
但是,当我通过推送通知打开应用程序时,当前台的应用程序收到推送通知,和时,这会触发。
我如何特别检测第二种情况?
答案 0 :(得分:36)
这里有两种情况需要以不同的方式检测:
React.PushNotificationIOS.getInitialNotification
方法检测到(以及获取通知的数据)。UIApplicationStateInactive
州(或'background'
州,正如React Native的AppStateIOS
类所称的那样)。处理这两种情况的代码(您可以将其放在index.ios.js
或其他在应用启动时运行的地方):
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;
}
});
答案 1 :(得分:8)
getInitialNotification
不适用于本地通知。不幸的是,从React Native的0.28开始,使用PushNotificationIOS.getInitialNotification()
时,本地推送通知启动时始终会返回null
值。
因此,您需要在launchOption
中将推送通知作为AppDelegate.m
抓取,并将其作为appProperty
传递给React Native。
以下是从背景/非活动状态的冷启动或接收本地推送通知所需的全部内容。
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");
}
}
确保从PushNotificationIOS
导入AppState
和react-native
。
我没有使用远程推送通知对此进行测试。也许@MarkAmery的方法适用于远程推送通知但不幸的是,从React Native的当前状态来看,这是我能够从冷状态工作中获得本地推送通知的唯一方法。
这在React Native中是高度无证的,所以我在他们的GitHub回购中创建了an issue以引起对它的注意,并希望能够纠正它。如果您正在处理此问题,请转到此处并竖起大拇指,使其渗透到顶部。
答案 2 :(得分:0)
我找到的解决方案有点hacky并且依赖于我注意到的关于事件处理程序触发的顺序的一些可能奇怪的行为。我一直在使用的应用程序需要相同的功能,以便在我通过推送通知打开应用程序时进行检测。
我发现PushNotificationIOS
的处理程序在AppStateIOS
的处理程序之前触发。这意味着,如果我将前台/后台状态保存到内存/ AsyncStorage,我可以检查它就像在PushNotification事件处理程序中那样:if (activity === 'background')
如果那是真的那么我就知道我刚从推送通知中打开了应用程序。
我总是将AppStateIOS
前景/后台活动保存在内存和磁盘上(分别使用redux和redux-persist),所以我只要在需要知道的时候检查它。
对于您的目的而言,这可能过于苛刻,并且该行为可能在将来发生变化,或者可能仅仅局限于我。尝试查看该解决方案,看看你的想法。