Receive location updates after application termination

I need to constantly monitor the user's location (but not drain the battery). I understand that the only way to get updates after the application finishes is to use startMonitoringSignificantLocationChanges.

From the Apple Location Programming Guide Location on startMonitoringSignificantLocationChanges:

If you run this service, and your application will subsequently, the system automatically restarts the application in the background if a new event occurs. In this case, the options are the dictionary passed to the application: didFinishLaunchingWithOptions: your application delegate method contains the UIApplicationLaunchOptionsLocationKey key to indicate that your application was launched due to a location event. After restarting, you still need to configure the location manager object and call this method to continue receiving location events. When you restart the location service, the current event is delivered to your delegate immediately. In addition, the location property of your location, the manager object is populated by the most recent location object, even before you start the location services.

I would be glad if someone can demonstrate in the code (example) which methods I should use

In the following code, I go to: - run the location manager in appdelegate, which will start updating the changes and starting the sign monitor update. - in didUpdateToLocation I call stopupdating - in didFinishLaunchingWithOptions when I check if I have a UIApplicationLaunchOptionsLocationKey to find out if I am in the background and running due to a strong update of the monitor location. - if so, I call startMonitoringSignificantLocationChanges again (I don’t know why ...) and start UIBackgeoundTaskIdentifier to call the startupdating method.

LocationController.m : + (LocationController*)sharedInstance { @synchronized(self) { if (sharedCLDelegate == nil) { [[self alloc] init]; } } return sharedCLDelegate; } - (id)init { self = [super init]; if (self != nil) { self.locationManager = [[[CLLocationManager alloc] init] autorelease]; self.locationManager.delegate = self; self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; [self.locationManager startUpdatingLocation]; [self.locationManager startMonitoringSignificantLocationChanges]; } return self; } - (void) startMonitoringSignificantLocationChanges { [self.locationManager startMonitoringSignificantLocationChanges]; } - (void) stopMonitoringSignificantLocationChanges { [self.locationManager stopMonitoringSignificantLocationChanges]; } -(void) start{ [self.locationManager startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) { self.lastLocation = newLocation; [self updateLocation]; //sending location to server [self.locationManager stopUpdatingLocation]; } } - (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error{ [self.locationManager stopUpdatingLocation]; } AppDelegate.h : @interface AppDelegate : NSObject <UIApplicationDelegate> { UIBackgroundTaskIdentifier bgTask; } AppDelegate.m : - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { id locationValue = [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]; if (locationValue) { [[LocationController sharedInstance] startMonitoringSignificantLocationChanges]; UIApplication *app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; [[LocationController sharedInstance] start]; //startupdating return YES; } else { [[LocationController sharedInstance] init]; } } -(void) applicationDidEnterBackground:(UIApplication *) application { NSLog(@"entered background Mode"); } -(void) applicationDidBecomeActive:(UIApplication *) application { NSLog(@"application Did Become Active"); } 

Thanks.

+4
source share
1 answer

Using your classes, I will do this.

In the AppDelegate.m application, when your application is in the foreground or in the background, I moved the CLLocationManager to run in the foreground / background to match. The reason I'm doing this is because if the CLLocationManager does not move to the background while the application is in the background, no location updates are sent to the CLLocationManager callback

 - (void)applicationDidEnterBackground:(UIApplication *) application { [[LocationController sharedInstance] stop]; [[LocationController sharedInstance] startMonitoringSignificantLocationChanges]; NSLog(@"entered background Mode"); } - (void)applicationDidBecomeActive:(UIApplication *) application { [[LocationController sharedInstance] stopMonitoringSignificantLocationChanges]; [[LocationController sharedInstance] start]; NSLog(@"application Did Become Active"); } 

So, let's say your application then moves to the background, and after a while, iOS decides to use it too much memory and kills your application.

After a few minutes, iOS then receives a location update and updates your application, letting it know that it appeared due to the location service. Then you need to restart the background location service, as that will be the only opportunity your application should do.

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) { [[LocationController sharedInstance] startMonitoringSignificantLocationChanges]; } return YES; } 

Oh, and the last change, I'm not sure why in your locationManager:didUpdateToLocation:fromLocation: you stop the location service, since when you do this, no more updates happen. Just leave it to work, and every time a change of location occurs, you can send it to the server.

 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) { self.lastLocation = newLocation; [self updateLocation]; //sending location to server } 
+11
source

All Articles