Detect if application: didReceiveRemoteNotification: fetchCompletionHandler: was called by tapping on a notification in Notification Center

application: didReceiveRemoteNotification: fetchCompletionHandler:

is different from

application: didReceiveRemoteNotification:

How? from the docs:

  • Custom nav bar styling - iOS
  • What is the best best way to disable cross fades on UICollectionView/UICollectionViewLayout rotates or bounds changes?
  • Auto Layout UILabels
  • Change a UILabels text with a UISliders value
  • Sound not working in iPhone Simulator?
  • UIScrollView with “Circular” scrolling
  • Unlike the application:didReceiveRemoteNotification: method, which is
    called only when your app is running, the system calls this method
    regardless of the state of your app. If your app is suspended or not
    running, the system wakes up or launches your app and puts it into the
    background running state before calling the method. If the user opens
    your app from the system-displayed alert, the system calls this method
    again so that you know which notification the user selected.

    My struggle is: I want to know if the method was called by the user tapping an a system-displayed alert from the Notification Center or from a silent push notification that wakes up the device. Currently, as far as I can see, there is no obvious way to differentiate.

    - (BOOL)application: didFinishLaunchingWithOptions:
    

    Tracking the launchOptions in the above method is not a solution because it’s only called if the app is suspended/not running in background. If it’s running in the background it doesn’t get called.

    6 Solutions Collect From Internet About “Detect if application: didReceiveRemoteNotification: fetchCompletionHandler: was called by tapping on a notification in Notification Center”

    The Apple docs are a bit confusing

    application: didReceiveRemoteNotification: fetchCompletionHandler:  
    

    is used if your application supports the remote-notification background mode (ie you’re doing BackgroundFetch.)

    application: didReceiveRemoteNotification:  
    

    is called when the OS receives a RemoteNotification and the app is running (in the background/suspended or in the foreground.)
    You can check the UIApplicationState to see if the app was brought to foreground by the user (tapping on notification) or was already running when notification comes in.

    - (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
          UIApplicationState state = [application applicationState];
            // user tapped notification while app was in background
        if (state == UIApplicationStateInactive || state == UIApplicationStateBackground) {
             // go to screen relevant to Notification content
        } else {
             // App is in UIApplicationStateActive (running in foreground)
             // perhaps show an UIAlertView
        }
    }
    

    You could check the UIApplication‘s applicationState to distinguish silent calls from calls made with the application being actively used by the user:

    typedef enum : NSInteger {
       UIApplicationStateActive,
       UIApplicationStateInactive,
       UIApplicationStateBackground
    } UIApplicationState;
    

    Or keep your own flag set on the delegate‘s applicationDidEnterBackground:.

    Application State is not reliable because if you have control center or Apple’s notification center open over your app, application: didReceiveRemoteNotification: fetchCompletionHandler: will get called and the application state will be Inactive.

    I’m having the same issue trying to respond to a click on the notification while the app is in the background and there doesn’t seem to be a reliable way to solely identify this.

    When application: didReceiveRemoteNotification:fetchCompletionHandler: method is called app state is UIApplicationStateInactive if user taps on alert (in this case you would like to prepare some UI) and is UIApplicationStateBackground when app is silently woken (in this case you just load some data).

    I’m not sure if I understand your question.

    Do you want to differentiate between a silent push notification background fetch and a noisy push notification? You can simply check whether the push notification dictionary contains the “content-available” key: [[userInfo objectForKey:@"aps"] objectForKey:@"content-available"] If it does, then it should be a silent push. If not, it was a normal push.

    Do you want to know if that background fetch method is called when the application receives a notification and it is in suspended/not running? If so, you can do the following:

    • Download and import LumberJacks into your app. Look through the directions and learn how to set it up such that you can save logs to the disk.
    • Put this in any method you want to see whether/when that method is invoked:

      • DDLogDebug(@"%@ - %@",NSStringFromSelector(_cmd),NSStringFromClass([self class]));

      This will print the class and the method to the log file.

    • Examine the log file after sending yourself a push notification to your background-fetch enabled app, and see if any of the methods get called by looking at your log file.

    If you have set up your app correctly for background fetch, the method application: didReceiveRemoteNotification: fetchCompletionHandler: will be called even when the app is backgrounded/not running if you receive a push notification (silent push or not).

    In case of swift

    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    
        let state : UIApplicationState = application.applicationState
        if (state == .Inactive || state == .Background) {
            // go to screen relevant to Notification content
        } else {
            // App is in UIApplicationStateActive (running in foreground)
        }
    }