Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will iOS wake up the terminated app if it's registered with location for UIBackgroundModes?

Tags:

I know that if an app uses "The significant-change location service", iOS will wake it up if there's a location update to be delivered, even if the app is terminated.

I couldn't find a clear answer about the case if the app is using standard location services and specifies location as the key for UIBackgroundModes: Will iOS also wake it up to deliver the update even if it's terminated? Or does the app need to be running in the background to get the location update callback?

UPDATE: At the time I was asking this, I didn't have the time to test it. But after I got an answer here, I wrote this piece of code in my application's delegate to see if my terminated app will be relaunched when it gets a location update. I'm displaying a UILocalNotification when I'm notified of the update. However, when I terminated my app and then changed my location in the city, the app was not relaunched and I didn't get any updates. Can you tell me what it's that I'm doing wrong?

UPDATE #2: According to the final findings in this Q&A, there's nothing wrong with this code and it's the expected behaviour for an app that uses standard location services, not to be relaunched after termination.

I've added location as one of the UIBackgroundModes in the Info.plist file.

And this is the location related parts of my app delegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {          [UIApplication sharedApplication].applicationIconBadgeNumber = 0;      m_locManager = [[CLLocationManager alloc] init];     m_locManager.delegate = self;     [m_locManager startUpdatingLocation];     return YES; }  - (void)applicationDidEnterBackground:(UIApplication *)application {     [m_locManager startUpdatingLocation]; }  - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {     NSLog("%@", [NSString stringWithFormat:@"Background Fail %@", [error localizedDescription]]); }  - (void)locationManager:(CLLocationManager *)manager     didUpdateToLocation:(CLLocation *)newLocation            fromLocation:(CLLocation *)oldLocation {     UILocalNotification * theNotification = [[UILocalNotification alloc] init];     theNotification.alertBody = [NSString stringWithFormat:@"Background location %.06f %.06f %@" , newLocation.coordinate.latitude, newLocation.coordinate.longitude, newLocation.timestamp];     theNotification.alertAction = @"Ok";      theNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];      [[UIApplication sharedApplication] scheduleLocalNotification:theNotification]; } 
like image 762
aslisabanci Avatar asked Sep 02 '12 21:09

aslisabanci


People also ask

Will iOS terminate the app running in background after a specific time?

No, there is no specific time defined for this.

When app is killed iOS?

It varies per device, and is tighter on older devices. Prior to iPhone 6s, this limit is around 200 MB max, but after 6S, it grows higher. When this limit is exceeded, your app will be killed immediately. “jetsam” is what's known as a “Memory Pressure Exit”, and is the most common type of app termination.


2 Answers

Looks like you found a workable solution and it seems like using the significant change framework would save you some battery life, so long as it is accurate enough for your purposes. Your solution is also beneficial because it allows you to juggle potentially more than the per-app limit of 20 regions allowed to be simultaneously monitored, by only monitoring those regions that you are closest to.

I need similar functionality, but don't think the significant change would be accurate enough for my app, so I dug around some more and found the following.

Per the Location Awareness Programming Guide, under "Monitoring Shape-Based Regions":

In iOS, regions associated with your app are tracked at all times, including when your app is not running. If a region boundary is crossed while an app is not running, that app is relaunched into the background to handle the event. Similarly, if the app is suspended when the event occurs, it is woken up and given a short amount of time to handle the event.

And also in "Handling Boundary-Crossing Events for a Region":

Every time the user’s current location crosses a boundary region, the system generates an appropriate region event for your app. If your app is already running, these events go directly to the delegates of any current location manager objects. If your app is not running, the system launches it in the background so that it can respond. Apps can implement the following methods to handle boundary crossings:

locationManager:didEnterRegion:

locationManager:didExitRegion:

In my case, I just needed to fire a notification when the boundary was crossed, so I set my AppDelegate to conform to CLLocationManagerDelegate, created a locationManager property, and put this in my implementation file:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {     self.locationManager.delegate = self;     return YES; }  - (CLLocationManager *)locationManager {     if (!_locationManager) {         _locationManager = [[CLLocationManager alloc] init];         _locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;     }     return _locationManager; }  - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {     UILocalNotification *notification = [[UILocalNotification alloc] init];     notification.alertBody = NSLocalizedString(@"You crossed a boundary!", @"user crossed a boundary");     [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; } 

Testing shows this works without the UIBackgroundModes location key needing to be set. In this use-case, the OS handles boundary monitoring for you and then sends the event to your app just long enough to process the event. This doesn't launch the app, it just runs it in the background for a few seconds to process the boundary event, during which time you can only do relevant activities. Hope this helps someone else, too!

like image 130
Daniel J Avatar answered Jun 23 '23 21:06

Daniel J


Yes, it will behave the same way except it will receive updates more often (and thus consume more battery).

Source: App States and Multitasking under the section Tracking the User's Location.

EDIT After re-reading, it seems that the program will be woken up from a suspended state but not a terminated one. I don't think you really need this background mode, though. It is designed for apps that need fine location info (like turn-by-turn navigation). Check out the section in the Location Programming guide about "region based" programming. The example in your comments is listed as one of the uses of this app.

EDIT AGAIN As per the discussion in the comments, the final solution seems to be setting significant location change until the user is close enough, and then switching over to fine location change (and hoping the app doesn't get terminated during that time ^^)

like image 38
borrrden Avatar answered Jun 23 '23 23:06

borrrden