簡體   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