it-swarm.com.ru

Фоновые службы определения местоположения не работают в iOS 7

Я недавно обновил свои устройства iOS для использования iOS 7. Одно из разрабатываемых нами приложений использует фоновые службы определения местоположения для отслеживания местоположения устройства, и все наши тестеры сообщили, что приложение больше не отображается для отслеживания в фоновом режиме под iOS 7. 

Мы убедились, что фоновая настройка для приложения включена в настройках устройства, и предыдущая сборка работала безупречно под iOS 6. Даже если устройство было зациклено, приложение перезапустится после обновления местоположения. 

Есть ли что-то еще, что нужно сделать, чтобы это работало под iOS 7? 

34
Alan Samet

Вот решение, которое я использовал для получения непрерывного местоположения от устройств iOS 7, независимо от того, находится оно на переднем плане или на заднем плане.

Вы можете найти полное решение и объяснение в блоге, а также на github: -

  1. Программирование обновления фонового местоположения для iOS 7 и 8

  2. Github Project: Программирование фонового обновления местоположения для iOS 7 и 8

Методы и объяснение: -

  1. Я перезапускаю диспетчер местоположений каждую 1 минуту в функции didUpdateLocations

  2. Я позволяю диспетчеру местоположений получать местоположения от устройства в течение 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, даже когда оно приостановлено

47
Ricky

Если вы посмотрите видео сессия WWDC 2013 № 204 - Что нового в многозадачности pdf, на странице № 15 ясно упоминается, что приложения не будут запускаться в фоновом режиме, если пользователь убьет его из переключателя приложений. Пожалуйста, смотрите изображение,

enter image description here

18
Obj-Swift

Я думаю, что они сделали оптимизацию (возможно, с использованием датчиков движения), чтобы обнаружить «относительно» стационарное позиционирование телефона, и они останавливают обновления местоположения. Это только предположение, но мои тесты в настоящее время показывают:

  1. Начальные локации обновлений; (проверено с точностью 10 и 100 метров, 3 раза каждый)
  2. Выключите экран устройства, чтобы поместить приложение в фоновом режиме;
  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;
    }
}
16
Nikolay Tsenkov

Одно из моих приложений для 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/

7
androidExplorer

Я нашел другой поток Запустите 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

5
Ricky

Значок в строке состояния включен? Это странное поведение, которое я имел тоже . Проверьте мой вопрос: startMonitoringSignificantLocationChanges, но через некоторое время didUpdateLocations больше не вызывается

Я обнаружил, что произошли значительные изменения местоположения, но простая остановка и перезапуск службы (для значительных изменений) не приводили к запуску новых местоположений.

1
Mr. Cobblepot

Вы должны установить для свойства pausesLocationUpdatesAutomatically класса CLLocationManagerclass значение false , чтобы отключить систему от приостановки обновления местоположения.

0
Tibin Thomas