Фоновые службы определения местоположения не работают в iOS 7
Недавно я обновил свои устройства iOS для использования iOS 7. Одно из разрабатываемых нами приложений использует фоновые службы определения местоположения для отслеживания местоположения устройства, и все наши тестеры сообщили, что приложение больше не отображается для отслеживания в фоновом режиме под iOS 7.
Мы убедились, что фоновая настройка для приложения включена в настройках устройства, и предыдущая сборка работала безупречно под iOS 6. Даже если устройство было зациклено, приложение перезапустится после обновления местоположения.
Есть ли что-то еще, что нужно сделать, чтобы это работало под iOS 7?
7 ответов
Вот решение, которое я использовал для получения непрерывного местоположения от устройств iOS 7, независимо от того, находится ли оно на переднем плане или на заднем плане.
Вы можете найти полное решение и объяснение в блоге, а также на github:-
Программирование обновления фонового местоположения для iOS 7 и 8
Github Project: программирование фонового обновления местоположения для iOS 7 и 8
Методы и объяснение: -
Я перезапускаю диспетчер местоположений каждую 1 минуту в функции didUpdateLocations
Я позволяю диспетчеру местоположений получать местоположения от устройства в течение 10 секунд, а затем выключить его (для экономии заряда аккумулятора).
Частичный код ниже: -
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
for(int i=0;i<locations.count;i++){
CLLocation * newLocation = [locations objectAtIndex:i];
CLLocationCoordinate2D theLocation = newLocation.coordinate;
CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 30.0)
continue;
//Select only valid location and also location with good accuracy
if(newLocation!=nil&&theAccuracy>0
&&theAccuracy<2000
&&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){
self.myLastLocation = theLocation;
self.myLastLocationAccuracy= theAccuracy;
NSMutableDictionary * dict = [[NSMutableDictionary alloc]init];
[dict setObject:[NSNumber numberWithFloat:theLocation.latitude] forKey:@"latitude"];
[dict setObject:[NSNumber numberWithFloat:theLocation.longitude] forKey:@"longitude"];
[dict setObject:[NSNumber numberWithFloat:theAccuracy] forKey:@"theAccuracy"];
//Add the vallid location with good accuracy into an array
//Every 1 minute, I will select the best location based on accuracy and send to server
[self.shareModel.myLocationArray addObject:dict];
}
}
//If the timer still valid, return it (Will not run the code below)
if (self.shareModel.timer)
return;
self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager];
[self.shareModel.bgTask beginNewBackgroundTask];
//Restart the locationMaanger after 1 minute
self.shareModel.timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self
selector:@selector(restartLocationUpdates)
userInfo:nil
repeats:NO];
//Will only stop the locationManager after 10 seconds, so that we can get some accurate locations
//The location manager will only operate for 10 seconds to save battery
NSTimer * delay10Seconds;
delay10Seconds = [NSTimer scheduledTimerWithTimeInterval:10 target:self
selector:@selector(stopLocationDelayBy10Seconds)
userInfo:nil
repeats:NO];
}
Обновление от мая 2014: я получил несколько запросов на добавление примеров кодов при отправке местоположения на сервер в течение определенного промежутка времени. Я добавил примеры кодов, а также объединил исправление для BackgroundTaskManager, чтобы решить проблему с фоном, работающим в течение длительного периода времени. Если у вас есть какие-либо вопросы, приглашаем вас присоединиться к нам для обсуждения здесь: Фоновое обновление местоположения Программирование для iOS 7 с обновлением местоположения для обсуждения на сервере
Обновление в январе 2015 года: если вы хотите получать обновление местоположения, даже когда приложение приостановлено, см. Раздел: Получение обновлений местоположения для приложения iOS, даже когда оно приостановлено.
Если вы посмотрите видео сессия WWDC 2013 №204 - Что нового в многозадачности pdf, на странице № 15 ясно упоминается, что приложения не будут запускаться в фоновом режиме, если пользователь убьет их из переключателя приложений. Пожалуйста, смотрите изображение,
Я думаю, что они сделали оптимизацию (возможно, с использованием датчиков движения), чтобы обнаружить "относительно" стационарное позиционирование телефона, и они останавливают обновления местоположения. Это только предположение, но мои тесты в настоящее время показывают:
- Начальные локации обновлений; (проверено с точностью 10 и 100 метров, 3 раза каждый)
- Выключите экран устройства, чтобы поместить приложение в фоновом режиме;
- Оставьте устройство неподвижным (например, на столе) на 30 минут.
Данные, которые я записываю, показывают, что гео-обновления прекращаются через ~ 15 м и 30 с. При этом вся другая фоновая обработка, которую вы делаете, также прекращается.
Моим устройством является iPhone 5 с iOS 7.
Я на 95% уверен, что это не так на iOS 6/6.1. Где для получения гео-обновлений с точностью до 100 м используется непрерывная работа в фоновом режиме.
Обновить
Если вы перезапускаете диспетчер местоположений каждые 8 минут, он должен работать непрерывно.
Обновление № 2
Я не проверял это в последнем, но именно так я перезапустил его, когда писал пост. Я надеюсь, что это полезно.
- (void)tryRestartLocationManager
{
NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
int seconds = round(floor(now - locationManagerStartTimestamp));
if ( seconds > (60 * 8) ) {
[locationManager stopUpdatingLocation];
[locationManager startUpdatingLocation];
locationManagerStartTimestamp = now;
}
}
Одно из моих приложений для iOS должно отправлять обновление местоположения на сервер через регулярные промежутки времени, и следующий подход сработал для нас....
Начиная с iOS 7:
- приложение должно уже использовать службы определения местоположения (startUpdatingLocation) ДО того, как оно будет фоновым, чтобы иметь право на фоновое время выполнения
- тайм-аут фонового периода был сокращен с 10 до 3 минут
- остановка обновлений местоположения (через stopUpdatingLocation) запустит 3-минутный обратный отсчет backgroundTimeRemaining
- начальное обновление местоположения, пока оно уже в фоновом режиме, не будет сбрасывать backgroundTimeRemaining
Таким образом, НЕ ОСТАНАВЛИВАЙТЕ обновления местоположения в любое время... Вместо этого, предпочтите использовать необходимую точность (точное местоположение против грубого местоположения). Грубое расположение не потребляет много батареи... так что это решение решает вашу проблему.
После долгих поисков в Интернете, нашел ссылку, которая обеспечивает жизнеспособное решение для iOS 7. Решение заключается в следующем:
- Пока приложение находится на переднем плане, запустите обновления местоположения (startUpdatingLocation), но установите фильтры точности и расстояния на очень подробные (например, 3 км) обновления. Важно сделать это на переднем плане (в applicationDidEnterBackground слишком поздно).
- Когда требуется детализированное разрешение, временно установите фильтры точности и расстояния, чтобы получить наилучшее возможное местоположение, а затем верните их обратно к детализированным значениям, но никогда не останавливайте обновления местоположения.
- Поскольку обновления местоположения всегда включены, приложение не будет приостановлено при переходе в фоновый режим.
И убедитесь, что вы добавили следующее в Info.plist вашего приложения "location" в ключ UIBackgroundModes "location-services" и "gps" в ключ UIRequiredDeviceCapabilities
Кредиты: http://gooddevbaddev.wordpress.com/2013/10/22/ios-7-running-location-based-apps-in-the-background/
Я нашел другую ветку Start Location Manager в iOS 7 из фоновой задачи. Sash упомянул, что
Я нашел проблему / решение. Когда пришло время запустить службу определения местоположения и остановить фоновую задачу, фоновую задачу следует остановить с задержкой (я установил 1 секунду). В противном случае служба определения местоположения не запустится.
Кто-нибудь может попробовать и проверить?
Николай, ты можешь вставить свой код сюда? Я пытался перезапустить диспетчер местоположения каждые 8 минут, но он не работает непрерывно.
Обновить:
После поиска High и Low я нашел решение от Apple Forum!
В iOS 7 нельзя запускать службу определения местоположения в фоновом режиме. Если вы хотите, чтобы служба определения местоположения продолжала работать в фоновом режиме, вы должны запустить ее на переднем плане, и она будет продолжать работать в фоновом режиме.
Если вы похожи на меня, остановите службу определения местоположения и используйте таймер, чтобы перезапустить ее в фоновом режиме, она НЕ будет работать.
Для получения более подробной информации вы можете посмотреть первые 8 минут видео 307 с WWDC 2013: https://developer.apple.com/wwdc/videos/
Обновление за февраль 2014 года: я могу получать местоположение постоянно с устройства, использующего iOS 7, после нескольких месяцев попыток. Вы можете увидеть полный ответ здесь: Фоновые службы определения местоположения не работают в iOS 7
Значок в строке состояния включен? Странное поведение у меня тоже. Проверьте мой вопрос: startMonitoringSignificantLocationChanges, но через некоторое время didUpdateLocations больше не вызывается
Я обнаружил, что произошли значительные изменения местоположения, но простая остановка и перезапуск службы (для значительных изменений) не приводили к запуску новых местоположений.
Вы должны установить pausesLocationUpdatesAutomatically
собственностью CLLocationManager
класс в false, чтобы отключить систему от приостановки обновления местоположения.