Подтвердить что ты не робот

Определите, было ли открыто приложение React Native iOS через push-уведомление

Обнаруживать, было ли приложение запущено/открыто из push-уведомления, описано, как определить, было ли открыто приложение iOS для родного (то есть, либо запущено, либо просто активировано ) через пользователя, нажимая push-уведомление.

Как я могу сделать то же самое в React Native? PushNotificationIOS позволяет подключить прослушиватель уведомлений...

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

но это срабатывает как при получении push-уведомления с приложением на переднем плане, так и при открытии приложения через push-уведомление.

Как я могу определить второй случай в частности?

4b9b3361

Ответ 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 активность переднего плана/фона в памяти и на диске (с использованием сокращений и сокращений), поэтому я просто проверяю это, когда мне нужно знать.

Это может быть слишком хаки для ваших целей, и это поведение может измениться в будущем, или оно может быть локализовано только для меня. Попробуйте взглянуть на это решение и посмотреть, что вы думаете.