Обновление местоположения в фоновом режиме и приостановленных режимах приложения
Я хочу написать приложение, которое каждые 5 минут отправляет серверу низкоточное местоположение для обоих режимов: переднего плана и фона. Поскольку я не хочу уменьшать заряд батареи, а locationSignificantChange дает только значения с высокой точностью, я запускаю/останавливаю местоположениеОбновление от GPS каждые 5 мин. Приложение работает отлично от режима переднего плана, но работает только около 1 часа из фонового режима (и останавливается, чтобы отправить местоположение после этого). Я думаю, что я пропускаю что-то в backgroundTask/NSTimer, потому что я новичок в iOS. Я буду очень благодарен за вашу помощь. Приложение будет работать только для iOS 7 и выше.
В общем, мой алгоритм:
** 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
Это мой код:
- (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:
Как я понял из iOS7 Apple хочет, чтобы startUpdatingLocation для locationManager выполнялся только с переднего плана. Итак, любые идеи для решения этой проблемы?
Я также попробовал дополнительное решение: вместо stop/startUpdatingLocation с NSTimer, чтобы изменить точность и расстояниеFilter для больших/малых значений с помощью NSTimer. Это не сработало, потому что я получаю триггер в "didUpdateLocations:" прослушиватель 4 раза для "freeway drive" вместо одного раза.
Ответы
Ответ 1
Менеджер местоположений будет определять для себя наименьшее действие, основанное на ваших настройках. Задайте параметры, подходящие для вашего прецедента, а затем ответственно ответьте в своем делетете. Проверьте полученные местоположения, если они слишком свежи, и вы ничего не делаете. Это позволит вашей обработке приложений воздействовать на аккумулятор как можно меньше.
significantLocationChanges
предназначен для снижения воздействия, и, по моему опыту, он неплохо справляется с этим. Другой вариант - использовать мониторинг региона или вместе с ним.
Вы можете дополнительно ограничить активность, создав области размера, основанные на точности, которую вы хотите достичь. Обновление регионов и сохранение местоположения только по мере пересечения границ. Это может быть более подходящим для ваших нужд.
Ответ 2
Чтобы получить обновление местоположения, когда приложение находится в фоновом режиме, и когда приложение приостановлено, это 2 очень разных сценария. Вам придется обращаться с ними по-другому.
Чтобы получить обновление местоположения, когда
A) Приложение находится в фоновом режиме, см. раздел Справочные службы, не работающие в iOS 7
B) Приложение приостановлено/завершено, см. Как получить обновления местоположения для iOS 7 и 8 Даже при приостановке приложения
Исходные коды для вышеуказанного сценария доступны в GitHub.