How to catch all iOS Push Notifications with different user actions including tap on app icon
Asked Answered
M

5

26

As per the Apple guide:

"As a result of the presented notification, the user taps the action button of the alert or taps (or clicks) the application icon. If the action button is tapped (on a device running iOS), the system launches the application and the application calls its delegate’s application:didFinishLaunchingWithOptions: method (if implemented); it passes in the notification payload (for remote notifications) or the local-notification object (for local notifications).

If the application icon is tapped on a device running iOS, the application calls the same method, but furnishes no information about the notification . If the application icon is clicked on a computer running Mac OS X, the application calls the delegate’s applicationDidFinishLaunching: method in which the delegate can obtain the remote-notification payload."

My question is Suppose user got 3-4 Push notifications from provider and all are stored in apple's notification center. If user tapped on notification alert, he/she can easily get the notification data in the app. But if user tapped app icon on iPhone, how to get all the data related of all previous notifications.

Thanks in advance!

Mitziemitzl answered 2/7, 2012 at 9:3 Comment(0)
Z
41

You can't, you will only receive information about the notification that was used to open your app.

So if a user opens your app, and your app has notifications, you will not be able to retrieve them from with in your app.

A work around could be to also keep track of notification on a server and handle this with in the app. Thus the server keeps track on which notification has been read. This is how Facebook does it.

Zabrine answered 2/7, 2012 at 9:11 Comment(4)
Thanks man! Actually I also had the same thoughts. But I was not sure. So that means to read the notification, user has to click on the notification bar. Right?Mitziemitzl
Yes, and you will only receive the notification that the user clicked on.Zabrine
Come again, after keeping track of which one is read, do you mean that the server will resend the ones in proprietary fashion when the App connects to the facebook server?Wampumpeag
I wonder why apple don't care about these basic issues.. Android is way good in handling push notifications..Bouie
S
16

To do it in a right way, some conditions must be met:

Your server knows about what your app currently have seen and what notifications it could send once again.

Let's consider only remote notifications. There are three states of app:

  • FOREGROUND:

    • notification appears without user's action:

      func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
          //handle your notification
      }
      

    You can display banner using third party library: BSForegroundNotification

  • BACKGROUND

    • notification appears on the screen. (Note that setting content-available=1 in a push notification can lead to the latest push message being visible once the app icon is pressed, as didReceive... is called).

      //nothing is called in the app, but app icon badge changes
      // OR - if the notification contains the field content-available set to 1 - 
      func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
          //handle your notification
      } 
      
    • user tap on notification

      func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
          //handle your notification
      }           
      
    • user take notification action

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action
      }
      

      or

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], withResponseInfo responseInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action response info
      }
      
    • user tap app icon

      func applicationDidBecomeActive(application: UIApplication) {
          //fetch pending notifications from server
      }
      
  • NOT RUNNING AT ALL

    • notification appears on the screen.

      //nothing is called in the app, but app icon badge changes
      
    • user tap on notification

      func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
          if let userInfo = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject: AnyObject] {
              //handle your notification
          }
      }
      
    • user take notification action

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action
      }
      

      or

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], withResponseInfo responseInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action response info
      }
      
    • user tap app icon

      func applicationDidBecomeActive(application: UIApplication) {
          //fetch pending notifications from server
      }
      

How to handle notification?

  1. let notification = WLNotification(userInfo: userInfo)

    Within WLNotification remember to keep current application state when you receive notification. In future you may need it to know where that notification come from.

  2. WLNetworkClient.sharedClient().notificationForIdentifier(notification.identifier)

    Fetch from server details about that notification, and in the same time let it know that you REALLY get that notification, and effected on user's data.

How to fetch all pending notifications?

WLNetworkClient.sharedClient().pendingNotificationsWithCompletionBlock(nil)

Fetch all notifications you missed. in other words, fetch those ones, which were not marked in server as received by you.

Read Limitations of Apple Push Notifications.

See the related questions:

Submerged answered 26/9, 2015 at 9:27 Comment(1)
Excellent @Bartłomiej SemańczykRubicon
Y
3

I had the same problem: if user clicks on push banner he gets info of push in app, if he clicks on app icon he doesn't get it. You can handle derivative one from it, but with some limits only. Example, if you want to have a badge number from push, you can do it: (Push -> App icon -> App icon badge -> your var)

in AppDelegate

- (void)applicationWillEnterForeground:(UIApplication *)application
{ 
    newMessages = application.applicationIconBadgeNumber;
}
Yukikoyukio answered 3/3, 2015 at 16:18 Comment(2)
I wonder if applicationDidBecomeActive might be a better place to test? In my case, I was wanting to display an alert.Nadabus
Sure, you can use applicationDidBecomeActive. It depends on your logics order for waking up of app. Method applicationWillEnterForeground launch before applicationDidBecomeActive.Yukikoyukio
M
1

Conceptually when application is loaded with clicking alert view presented for Push notification, than application is launched with didReceiveLocalNotification delegate method if your application is in background. At this point applicationDidFinishLaunching delegate method is not called.

When your application is not in background, clicking alert view presented for Push notification will call applicationDidFinishLaunching method.

Hope this clears your understanding between these 2 delegate methods.

Maddie answered 2/7, 2012 at 9:12 Comment(0)
L
-2

You can use this code:

 NSArray *pendingNotifications = [[[UIApplication sharedApplication] scheduledLocalNotifications] sortedArrayUsingComparator:^(id obj1, id obj2)                       {

        if ([obj1 isKindOfClass:[UILocalNotification class]] && [obj2 isKindOfClass:[UILocalNotification class]])
        {
            UILocalNotification *notif1 = (UILocalNotification *)obj1;
            UILocalNotification *notif2 = (UILocalNotification *)obj2;
            return [notif1.fireDate compare:notif2.fireDate];
        }

        return NSOrderedSame;
 }];

 // if there are any pending notifications -> adjust their badge number
 if (pendingNotifications.count != 0)
 {
     //do something
 }
Lilllie answered 27/8, 2014 at 17:38 Comment(2)
That's for local notifications, not push notifications.Grillroom
...and doesn't scheduledLocalNotifications only keep track of local notifications that have been scheduled, but not yet received? I think the original poster was asking about notifications that were received on the device, but that were not tapped. I, too, am interested to find out if this is possible with local notifications.Ginzburg

© 2022 - 2024 — McMap. All rights reserved.