I want to write application that every 5 min sends to server low-accuracy-location for its both modes: foreground and background. Because I don't want to reduce the battery charge and the locationSignificantChange gives only the high-accuracy-values, I start/stop locationUpdates from GPS every 5 min. Application works fine from foreground mode, but works only about 1 hour from background mode (and stops to send location afterwards). I guess I am missing something in backgroundTask/NSTimer code because I am new with iOS. I will very appreciate your help. The application will be only for iOS 7 and up.
In general my algorithm is follow:
** start backGroundTask
** [_locationManager startUpdatingLocation]
** handle received location in "didUpdateLocations:" listener
** [_locationManager stopUpdatingLocation]
** create new thread and fire the NSTimer with delay 5 min
** end backGroundTask
This is my code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self startLocationManager];
// .. other init app code
}
- (void) startLocationManager {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
_locationManager.distanceFilter = 10;
_locationManager.delegate = self;
_locationManager.pausesLocationUpdatesAutomatically = NO;
[_locationManager startLocation];
}
- (void) startLocation {
UIApplication * app = [UIApplication sharedApplication];
self.bkgdTask = [app beginBackgroundTaskWithExpirationHandler:^{
}];
[self.locationManager startUpdatingLocation];
}
- (void) stopUpdatingLocation {
[_locationManager stopUpdatingLocation];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
self.locationNextTimer = [NSTimer scheduledTimerWithTimeInterval:5 * 60
target:self
selector:@selector(startLocation)
userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:self.locationNextTimer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
[app endBackgroundTask:self.bkgdTask];
self.bkgdTask = UIBackgroundTaskInvalid;
});
}
- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[self.locationNextTimer invalidate];
self.locationNextTimer = nil;
//ToDo Location Handling
[self stopUpdatingLocation];
}
EDIT:
As I understood from iOS7 Apple wants that startUpdatingLocation for locationManager will be done only from foreground. So any ideas for solution of this problem? I also tried additional solution: instead stop/startUpdatingLocation with NSTimer, to change the accuracy and distanceFilter for big/small values with NSTimer. It did not work because I receive trigger in "didUpdateLocations:" listener 4 times for "freeway drive" instead of one time.