[Ios] 檢測應用是否從推送通知啟動/打開


Answers

晚但可能有用

當應用程序未運行時

  • (BOOL)應用程序:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

叫做 ..

你需要檢查推送通知

NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification) {
    NSLog(@"app recieved notification from remote%@",notification);
    [self application:application didReceiveRemoteNotification:notification];
} else {
    NSLog(@"app did not recieve notification");
}
Question

是否有可能知道應用程序是否從推送通知啟動/打開?

我想這個發布會可以在這裡抓到:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    if (launchOptions != nil) {
         // Launched from push notification
         NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

    }
}

但是,當應用程序在後台時,如何才能檢測到它是從推送通知中打開的?




為了迅速:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    PFPush.handlePush(userInfo)

    if application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background {
        //opened from a push notification when the app was on background

    }

}



如果有人想快速回答3

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    switch application.applicationState {
    case .active:
        //app is currently active, can update badges count here
        break
    case .inactive:
        //app is transitioning from background to foreground (user taps notification), do what you need when user taps here
        break
    case .background:
        //app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
        break
    default:
        break
    }
}



這個問題的問題是“打開”應用程序的定義不明確。 應用程序要么從非運行狀態冷啟動,要么從非活動狀態重新激活(例如從另一個應用程序切換回它)。 這是我的解決方案來區分所有這些可能的狀態:

typedef NS_ENUM(NSInteger, MXAppState) {
    MXAppStateActive = 0,
    MXAppStateReactivated = 1,
    MXAppStateLaunched = 2
};

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // ... your custom launch stuff
    [[MXDefaults instance] setDateOfLastLaunch:[NSDate date]];
    // ... more custom launch stuff
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // Through a lot of trial and error (by showing alerts), I can confirm that on iOS 10
    // this method is only called when the app has been launched from a push notification
    // or when the app is already in the Active state.  When you receive a push
    // and then launch the app from the icon or apps view, this method is _not_ called.
    // So with 99% confidence, it means this method is called in one of the 3 mutually exclusive cases
    //    1) we are active in the foreground, no action was taken by the user
    //    2) we were 'launched' from an inactive state (so we may already be in the main section) by a tap
    //       on a push notification
    //    3) we were truly launched from a not running state by a tap on a push notification
    // Beware that cases (2) and (3) may both show UIApplicationStateInactive and cant be easily distinguished.
    // We check the last launch date to distinguish (2) and (3).

    MXAppState appState = [self mxAppStateFromApplicationState:[application applicationState]];
    //... your app's logic
}

- (MXAppState)mxAppStateFromApplicationState:(UIApplicationState)state {
    if (state == UIApplicationStateActive) {
        return MXAppStateActive;
    } else {
        NSDate* lastLaunchDate = [[MXDefaults instance] dateOfLastLaunch];
        if (lastLaunchDate && [[NSDate date] timeIntervalSinceDate:lastLaunchDate] < 0.5f) {
            return MXAppStateLaunched;
        } else {
            return MXAppStateReactivated;
        }
    }
    return MXAppStateActive;
}

MXDefaults只是MXDefaults的一個小包裝。




發布這Xamarin用戶。

檢測應用程序是否通過推送通知啟動的關鍵是AppDelegate.FinishedLaunching(UIApplication app, NSDictionary options)方法以及傳入的選項字典。

如果選項字典是本地通知,則選項字典中將包含此密鑰: UIApplication.LaunchOptionsLocalNotificationKey

如果它是遠程通知,它將是UIApplication.LaunchOptionsRemoteNotificationKey

當密鑰為LaunchOptionsLocalNotificationKey ,該對象的類型為UILocalNotification 。 然後,您可以查看通知並確定它是哪個特定的通知。

提示: UILocalNotification中沒有標識符,與UNNotificationRequest一樣。 將字典密鑰放入包含requestId的UserInfo中,以便在測試UILocalNotification ,您將擁有一個特定的requestId以基於某些邏輯。

我發現,即使在使用UNUserNotificationCenterAddNotificationRequestUNMutableNotificationContent創建位置通知的iOS 10+設備上,當應用程序未運行(我殺死它),並通過點擊通知中心中的通知啟動時,字典仍包含UILocalNotificaiton對象。

這意味著我的代碼檢查基於通知的啟動將適用於iOS8和iOS 10+設備

public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
    _logger.InfoFormat("FinishedLaunching");

    if(options != null)
    {
        if (options.ContainsKey(UIApplication.LaunchOptionsLocalNotificationKey))
        {
            //was started by tapping a local notification when app wasn't previously running.
            //works if using UNUserNotificationCenter.Current.AddNotificationRequest OR UIApplication.SharedApplication.PresentLocalNotificationNow);

            var localNotification = options[UIApplication.LaunchOptionsLocalNotificationKey] as UILocalNotification;

            //I would recommended a key such as this :
            var requestId = localNotification.UserInfo["RequestId"].ToString();
        }               
    }
    return true;
}



IN SWIFT:

我正在運行推送通知(帶有後台提取)。當我的應用程序在後台並收到推送通知時,我發現appDelegate中的didReceiveRemoteNotification將被調用兩次; 一次用於收到通知時,另一次用戶單擊通知警報。

要檢測是否單擊通知警報,只需檢查appDelegate中的applicationState原始值== 1內部的didReceiveRemoteNotification。

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject: AnyObject]) {
    // If not from alert click applicationState(1)
    if (application.applicationState.rawValue != 1) {
        // Run your code here
    }
}

我希望這有幫助。




application:didReceiveRemoteNotification:檢查您的應用程序處於前景還是背景時是否收到通知。

如果它是在後台收到的,請從通知中啟動應用程序。

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
        NSLog(@"Notification received by running app");
    } else {
        NSLog(@"App opened from Notification");
    }
}



當應用程序在後台作為shanegao您可以使用

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground  )
    {
         //opened from a push notification when the app was on background
    }
}

但是如果你想啟動應用程序,當應用程序關閉,你想調試你的應用程序,你可以去編輯方案,並在左側菜單中選擇運行 ,然後在啟動選擇等待可執行文件啟動 ,然後你應用程序啟動,當你點擊推送通知

編輯方案>運行>等待可執行文件啟動




直接從文檔中

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo:nil

如果應用程序正在運行並收到遠程通知,則應用程序會調用此方法來處理通知。

此方法的實施應使用通知來採取適當的行動。

稍後一點

如果在推送通知到達時應用程序未運行,該方法將啟動應用程序並在啟動選項字典中提供適當的信息。

該應用程序不會調用此方法來處理推送通知。

相反,你的實現

application:willFinishLaunchingWithOptions:

要么

application:didFinishLaunchingWithOptions:

方法需要獲取推送通知有效載荷數據並進行適當的響應。







“未運行”狀態的Swift 2.0(本地和遠程通知)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {


// Handle notification
if (launchOptions != nil) {

    // For local Notification
    if let localNotificationInfo = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {

        if let something = localNotificationInfo.userInfo!["yourKey"] as? String {
            self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
        }


    } else

    // For remote Notification
    if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as! [NSObject : AnyObject]? {

        if let something = remoteNotification["yourKey"] as? String {
            self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
        }
    }

}


return true

}