Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: Push notifications, UIApplicationStateInactive and fast app switching

According to the Apple Docs, in order to find out if a user tapped on your push notification you are supposed to check the applicationState in application:didReceiveRemoteNotification:

If the value is UIApplicationStateInactive, the user tapped the action button; if the value is UIApplicationStateActive, the application was frontmost when it received the notification.

I have found that this is not always true. For example:

Double-tap the home button to reveal the system tray and enter "fast app switching mode", your application slides up to reveal other running applications and your app is put into the inactive state (even though it's still mostyle visible). If you receive a push notification in this mode your app delegate will still receive the application:didReceiveRemoteNotification: and at this point your applicationState is UIApplicationStateActive. According to the docs you should treat it like the user tapped the alert... but in this case they didn't. Not only that, the user didn't even see the push notification (possibly because the top of your application is cut off in this mode).

Does anyone know of a way to detect being in 'fast app switching mode' or handle the notification correctly?

like image 230
nrj Avatar asked Sep 09 '13 21:09

nrj


People also ask

Do push notifications work when app is closed iOS?

Apple does not offer a way to handle a notification that arrives when your app is closed (i.e. when the user has fully quit the application or the OS had decided to kill it while it is in the background). If this happens, the only way to handle the notification is to wait until it is opened by the user.

Why push notification is not working for iOS?

You can fix an iPhone that's not getting notifications by restarting it or making sure notifications are turned on. You should also make sure your iPhone is connected to the internet so apps can receive notifications. If all else fails, you should try resetting the iPhone — just make sure to back it up first.

Do push notifications work on iOS?

iOS. In iOS, users must explicitly sign up for push when they download your app. On iOS devices, push notifications appear in Apple's Notification Center, which a user can access by swiping down from the top of their screen.


1 Answers

I was able to fix it myself with some nifty checks...

Essentially the key to this whole thing is

-(void)applicationDidEnterBackground:(UIApplication *)application;

This method isn't called when you enter fast app switching (or control center) so you need to setup a check based on it.

@property                     BOOL isInBackground;
@property (nonatomic, retain) NSMutableArray *queuedNotifications;

And when you receive a notification...

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
 UIApplicationState appState = application.applicationState;
 // Check if we're in this special state. If so, queue the message up
 if (appState == UIApplicationStateInactive && !self.isInBackground) {
    // This is a special case in which we're in fast app switching or control center
    if (!self.queuedNotifications) {
        self.queuedNotifications = [NSMutableArray array];
    }

    // Queue this to show when we come back
    [self.queuedNotifications addObject:userInfo];
 }
}

And then when we come back...

- (void)applicationDidBecomeActive:(UIApplication *)application {
     application.applicationIconBadgeNumber = 0;


 if (!self.isInBackground) {
    // Show your notifications here

    // Then make sure to reset your array of queued notifications
    self.queuedNotifications = [NSMutableArray array];
 }
}

One more thing you may want to do is check for this special case of going to fast app switching and the user going somewhere else. I do this just before setting the isInBackground BOOL. I choose to send them as local notifications

-(void)applicationDidEnterBackground:(UIApplication *)application {

  for (NSDictionary *eachNotification in self.queuedNotifications) {
     UILocalNotification *notification = [self convertUserInfoToLocalNotification:eachNotification];
     [[UIApplication sharedApplication] scheduleLocalNotification:notification];
 }
 self.queuedNotifications = [NSMutableArray array];
 self.isInBackground = YES;
}
like image 185
Eric Busch Avatar answered Sep 19 '22 01:09

Eric Busch