i'm developing a sample app that tracks the user's position in background, but i don't want to leave the location service always enabled, but something in my timer does not behave properly.
My idea was that every x minutes, the service goes on, and when it have a correct new location it is released again, now is set to 10 seconds just for testing. (Significant LocationChange did not the trick, not accurated enough)
I was searching a lot (iOS Dev center + StackOverflow) and found the "new" background location features, that allows you to run code over 10 minutes after going to background, using beginBackgroundTaskWithExpirationHandler, a few blocks, and a timer.
I set the background mode to Location and by now i think i don't need to handle the end of the background time (first i want to get a location every 15-20 seconds)
the code is working "fine" but:
- The timer sometimes fires, sometimes does not.
- When the timer fires, it takes a minimum of 10 minutes to do it.
- Some random actions in the OS (like entering to search desktop) appears to estimulate the timer to fire (not sure of this, i don't realize how it is possible, but there it is...)
And by over the code will be another qüestion.
appdelegates's methods:
//applicationDidEnterBackground
- (void)applicationDidEnterBackground:(UIApplication *)application{
NSLog(@"to background");
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
_triggertimer = nil;
[self initTimer];
});
NSLog(@"backgroundTimeRemaining: %.0f", [[UIApplication sharedApplication] backgroundTimeRemaining]);}
//initTimer
- (void) initTimer{
NSLog(@"InitTimer ");
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
_triggertimer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:@selector(checkUpdates:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_triggertimer forMode:NSDefaultRunLoopMode] ;
[[NSRunLoop currentRunLoop] run];
}];}
//checkUpdates
- (void)checkUpdates:(NSTimer *)timer{
NSLog(@"CheckUpdates ");
UIApplication* app = [UIApplication sharedApplication];
if (nil == _locationManager) _locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = 10;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[_locationManager startUpdatingLocation];
[_locationManager startMonitoringSignificantLocationChanges];
double remaining = app.backgroundTimeRemaining;
NSLog(@"Reminaing %f", remaining);}
I tried lots of thing to try to fix this and maybe i messed or missed something... What do you see? maybe some concept errors, i'm trying to introduce myself to the blocks and I don't domain them yet ¬¬
By the way,why all the codes i've found contains this before doing anything with beginBackgroundTaskWithExpirationHandler?
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
I thought that this is for taking that 600 seconds of background... but i'm not sure!