iOS Not the typical background location tracking t

2019-01-25 01:09发布

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!

2条回答
甜甜的少女心
2楼-- · 2019-01-25 01:44

When your app is backgrounded the timer will no longer fire unless you have the "location" value for the UIBackgroundModes key set in the app's info.plist.

You can extend the time that you are allowed to run in the background (if you haven't set "location") using beginBackgroundTaskWithExpirationHandler but that should always be paired with the corresponding end call.

查看更多
淡お忘
3楼-- · 2019-01-25 01:49

Ok, the problem was that i was calling beginBackgroundTaskWithExpirationHandler twice, one in ApplicationDidEnterBackground and another one inside initTimer...

查看更多
登录 后发表回答