Determining if UILocalNotification fired with app in foreground or background

13,183

Solution 1

Maybe the easiest way is when your App is in Foreground, do not send a LocalNotification but just take your users to the event.

But if you insist on doing it by using LocalNotification, here is an easy way to detect what's your App's status when UILocalNotification fired.

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    //[super application:application didReceiveLocalNotification:notification]; // In most case, you don't need this line
    UIApplicationState state = [application applicationState];
    if (state == UIApplicationStateInactive) {
        // Application was in the background when notification was delivered.
    } else {

    }
}

Solution 2

This is what I added to the bodies of these functions... application didFinishLaunchingWithOptions:

NSUserDefaults* userDefaults= [NSUserDefaults standardUserDefaults];
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {  //launched from notification
    [userDefaults setBool:YES forKey:@"deactivate in-app notification"];
    [userDefaults synchronize];
}
else{
    [userDefaults setBool:NO forKey:@"deactivate in-app notification"];
    [userDefaults synchronize];
}

In applicationDidEnterBackground:

NSUserDefaults* userDefaults= [NSUserDefaults standardUserDefaults];
[userDefaults setBool:YES forKey:@"deactivate in-app notification"];
[userDefaults synchronize];

In applicationWillEnterForeground:

NSUserDefaults* userDefaults= [NSUserDefaults standardUserDefaults];
[userDefaults setBool:YES forKey:@"deactivate in-app notification"];
[userDefaults synchronize];

applicationDidBecomeActive:

NSUserDefaults* userDefaults= [NSUserDefaults standardUserDefaults];
[userDefaults setBool:NO forKey:@"deactivate in-app notification"];
[userDefaults synchronize];

didReceiveLocalNotification:

NSUserDefaults* userDefaults= [NSUserDefaults standardUserDefaults];
if(![userDefaults boolForKey:@"deactivate in-app notification"]){
    UIAlertView* alert= [[UIAlertView alloc]initWithTitle:@"My App" message:notif.alertBody delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
    [alert release];

    NSUserDefaults* userDefaults= [NSUserDefaults standardUserDefaults];
    [userDefaults setBool:NO forKey:@"deactivate in-app notification"];
    [userDefaults synchronize];
}

Now the two notifications are gone (particularly the one appearing when the app is in background and you open it from the notification alert.

Solution 3

In didReceiveLocalNotification you can check the application state:

[UIApplication shareApplication].applicationState

If it's equal to UIApplicationStateInactive you know that the app was in the background and the user opened it with the local notification alert.

if it's UIApplicationStateActive you may want to display your own alert to the user.

Share:
13,183
Admin
Author by

Admin

Updated on June 03, 2022

Comments

  • Admin
    Admin about 2 years

    When receiving a UILocalNotification

    1. The method application:DidReceiveLocalNotification is called when the app is in Foreground.
    2. When the app is in the Background, it opens the application and then calls application:DidReceiveLocalNotification.

    How can I determine which one of these scenarios are taking place? I would like to treat them differently.

    If the app was in the Background, then the user indicated they want to look at the event. So in application:DidReceiveLocalNotification I don't want to ask them again, I just want to take them to the event.

    But if the application is in the Foreground when the notification fires and calls application:DidReceiveLocalNotification, I want to ask the user if they want to view the event.

    In essence I would have:

    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    
    if (appLauncedFromBackground)
      // go to event
    else
      // ask if user wants to view event
    
    }
    

    I've thought of writing a bool value to an NSUserDefault inside applicationWillEnterForeground:application and then reading and resetting it inside application:DidReceiveLocalNotification. But I thought if there was a way to test, that would be a much better route.

    Thanks, Mark

    EDIT ******************************

    Thanks xuzhe but that isn't going to work in this situation. Here is a little more detail that may explain why it wont work and maybe help someone in answering this for me:

    The UILocalNotification that I am setting here is an event like a calendar event that is scheduled to fire at a user selected time so when scheduling the notification I will have no idea what the user is going to be doing when the notification fires. I am using the userInfo of the notification to store data about the event that is scheduled but setting a value like inBackground as suggested wont work.

    I do know it will be one of two situations if the user decides they want to "view" the event. (this all will assume the app is either in the background or foreground and NOT quit).

    1 - If it fires while the app is not being used && the app is in the background and not quit, iOS will notify the user that an event has occurred and provide an option for going to the responsible app (which is mine in this case). At that point assuming the user says "yes take me to this cool app" it will open the app from the background and call the application:DidReceiveLocalNotification where I can get all the notification userInfo.

    2 - The user, by chance, happens to be in my application when the scheduled event takes place. At that point the application:DidReceiveLocalNotification method is called again where I can then get all the notification userInfo.

    But it is at this point that I want to know which of the two scenarios just took place 1 or 2.

    Hope this additional detail about my use of the UILocalNotification will help in answering this question. Thanks in advance - mark

    END EDIT ****************************

  • Admin
    Admin almost 13 years
    I've edited the question to help better explain. And thanks, @xuzhe but this won't work for me. Im not setting off the LocalNotification, it is a UILocalNotification that has been scheduled to go off at some date. I therefore cant determine what the user will be doing at that time.
  • xuzhe
    xuzhe almost 13 years
    Edited the answer again. You can easily check your App's status by using UIApplicationState property.
  • Peter Sarnowski
    Peter Sarnowski over 12 years
    Very very nice. Fixed an issue I had for a quite some time.
  • charshep
    charshep over 12 years
    What about distinguishing between a return from background versus currently suspended due to an incoming phone call for example? Do we have to resort to setting flags in applicationDidEnterBackground/applicationWillEnterForeground or is there a better way?
  • klefevre
    klefevre over 9 years
    Is it really necessary to call super ?
  • xuzhe
    xuzhe over 9 years
    @kl94 In most case, it's not necessary to call super.