Определите, было ли открыто приложение React Native iOS через push-уведомление
Обнаруживать, было ли приложение запущено/открыто из push-уведомления, описано, как определить, было ли открыто приложение iOS для родного (то есть, либо запущено, либо просто активировано ) через пользователя, нажимая push-уведомление.
Как я могу сделать то же самое в React Native? PushNotificationIOS
позволяет подключить прослушиватель уведомлений...
PushNotificationIOS.addEventListener('notification', function (notification) {
console.log('got a notification', notification);
});
но это срабатывает как при получении push-уведомления с приложением на переднем плане, так и при открытии приложения через push-уведомление.
Как я могу определить второй случай в частности?
Ответы
Ответ 1
Здесь два случая должны быть обнаружены по-разному:
- Приложение полностью завершено (например, перезагрузив телефон или дважды нажав на него и вытащив его из списка приложений, работающих в фоновом режиме) и запускается пользователем при нажатии на push-уведомление. Это можно обнаружить (и полученные данные уведомления) с помощью метода
React.PushNotificationIOS.getInitialNotification
.
- Приложение было приостановлено и снова активировано нажатием кнопки на push-уведомлении. Просто как в родном приложении, вы можете сказать, что это происходит, потому что iOS передает уведомленное уведомление в ваше приложение, когда оно открывается (даже если это старое уведомление) и заставляет ваш обработчик уведомлений срабатывать, пока ваше приложение находится в состоянии
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;
}
});
Ответ 2
Для локальных уведомлений
getInitialNotification
не работает с локальными уведомлениями.
К сожалению, начиная с 0.28 из React Native использование PushNotificationIOS.getInitialNotification()
всегда возвращает значение null
при запуске с помощью локального уведомления Push.
Из-за этого вам нужно поймать push-уведомление как launchOption
в AppDelegate.m
и передать его в React Native как appProperty
.
Здесь все, что вам нужно получить локальное уведомление Push от холодного запуска или из фона/неактивного состояния.
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
.
Я не тестировал это с помощью Remote Push Notifications. Возможно, метод @MarkAmery отлично работает с Remote Push Notifications, но, к сожалению, с текущего состояния React Native это единственный способ получить локальные уведомления Push из холодного состояния.
Это очень не документировано в React Native, поэтому я создал проблему в своем репо GitHub, чтобы привлечь к ней внимание и, надеюсь, исправить ее. Если вы имеете дело с этим, идите туда и дайте ему большие пальцы вверх, чтобы он просачивался вверх.
https://github.com/facebook/react-native/issues/8580
Ответ 3
Решение, которое я нашел для этого, немного взломан и полагается на какое-то потенциально странное поведение, которое я заметил относительно порядка, который запускают обработчики событий. Приложение, над которым я работал, нуждался в такой же функциональности, чтобы обнаружить, когда я открываю приложение с помощью Push Notification.
Я обнаружил, что обработчик для PushNotificationIOS
срабатывает перед обработчиком для AppStateIOS
. Это означало, что если бы я сохранял состояние переднего плана/фона в памяти /AsyncStorage, я мог бы просто проверить его так, как в Обработчик событий PushNotification: if (activity === 'background')
, и если это правда, тогда я знал, что только что открыл приложение из Push Notification.
Я всегда сохраняю AppStateIOS
активность переднего плана/фона в памяти и на диске (с использованием сокращений и сокращений), поэтому я просто проверяю это, когда мне нужно знать.
Это может быть слишком хаки для ваших целей, и это поведение может измениться в будущем, или оно может быть локализовано только для меня. Попробуйте взглянуть на это решение и посмотреть, что вы думаете.