Отложенные обновления местоположения ios не могут отложить

Я изучаю использование отложенных обновлений местоположения для трекера активности iOS, который позволяет службам определения местоположения работать в фоновом режиме. Я реализовал предложенные фрагменты кода (см. Ниже). В отладке XCode отложенные местоположения пытаются начать несколько раз, пока данные местоположения не входят приблизительно в 1 в секунду. После этого он утверждает, что преуспел в запуске отсрочек, и обратный вызов для триггера финиша также завершается успешно после истечения указанного периода времени. Однако в течение времени обработчик местоположения все еще выполняется один раз в секунду. Я читал, что это потому, что телефон не считает себя готовым войти в фон, и что тестирование в XCode делает это. Обратите внимание, что обработчик события "didEnterBackground" в AppDelegate вызывается сразу при выключении экрана и возобновляется при повторном открытии приложения.

Я запустил тот же код с отключенным телефоном, как в другом тесте, рядом с окном с GPS, выключенным экраном или переключением на совершенно другие приложения, и он все еще фактически не откладывает обновления. Я могу сказать, потому что сетевое обновление по-прежнему происходит каждые 30 секунд вместо интервала в 120 секунд, который требуется в приведенном ниже примере кода.

Что еще нужно для того, чтобы фактически заставить работать отсрочку, поскольку при их запуске не происходит ошибок, и они действительно получают свой завершающий обратный вызов? Почему обновления местоположения продолжаются со скоростью 1 в секунду, даже если приложение переходит в фоновый режим?

Iphone 5s, IOS 7.1.1

// .h file (partial)
@interface MotionTracker : NSObject<CLLocationManagerDelegate, UIAccelerometerDelegate> 

@property (strong, nonatomic) CLLocationManager *locationManager;

@end

// .m file (parial)
- (id) init {
    if(self = [super init]){
        _locationManager = [[CLLocationManager alloc] init];
        _locationManager.delegate = self;
        _locationManager.distanceFilter = kCLDistanceFilterNone; 
        _locationManager.desiredAccuracy = kCLLocationAccuracyBest;

        // if set to YES (default), app stops logging location at some point and doesn't resume in any timely fashion, all data points lost in between
        _locationManager.pausesLocationUpdatesAutomatically = NO;

        _locationManager.activityType = CLActivityTypeFitness; 
    }
    return self;
}

// called early in program after login confirmed
- (void) startCollectingLocation {
    [_locationManager startUpdatingLocation];
}    

- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations {

    // logs to file when device is not in debug
    // always returns 1
    NSLog(@"Location update count: %d",[locations count]);

    // some code here to handle location updates
    // - collect key location day in NSDictionary
    // - every N seconds send Network call to server to save (have tried 30 seconds, 15 minutes, 30 minute network intervals). Have also tried turning off network calls completely.


    // deferred updates starter
    if (!self.deferringUpdates) {
        if([CLLocationManager deferredLocationUpdatesAvailable]){
            [_locationManager allowDeferredLocationUpdatesUntilTraveled:500 timeout:(NSTimeInterval)120]; // (have also tried large numbers, and "Infinite"
            self.deferringUpdates = YES;
            NSLog(@"Deferred updates start");
        } else {
            NSLog(@"Deferred updates not available");
        }
    }
}

- (void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
    if(!error){
        _deferringUpdates = NO;
        NSLog(@"Deferred updates: finished");
    } else {
        _deferringUpdates = NO;
        NSLog(@"Deferred updates: %@", [error localizedDescription]);
    }
}

3 ответа

Если устройство подключено к отладчику или к зарядному устройству, оно останется включенным (не в спящем режиме) и, следовательно, не перейдет в отложенный режим. Отложенный режим - это оптимизация питания, позволяющая устройству спать. Если устройство не запланировано для сна по другим причинам, включение отложенного режима не заставит его спать в противном случае. Попробуйте свой тест, убедившись, что другие приложения не используют службы определения местоположения, и отключите его от зарядного устройства с выключенным экраном. После запуска в течение некоторого времени, подключитесь снова и проверьте свои журналы, вы должны увидеть, что устройство отключилось и отложил обновления.

От Apple allowDeferredLocationUpdatesUntilTraveled:timeout: документация:

Отложенные обновления доставляются только тогда, когда система переходит в состояние низкого энергопотребления. Отложенные обновления не происходят во время отладки, потому что XCode препятствует тому, чтобы Ваше приложение спало и таким образом препятствует тому, чтобы система вошла в то состояние низкого энергопотребления.

Стоит также отметить, что отложенные обновления доступны только в том случае, если для locationManager.desiredAccuracy установлено значение kCLLocationAccuracyBest OR kCLLocationAccuracyBest; locationManager.distanceFilter также должен иметь значение kCLDistanceFilterNone.

Из документации Apple:

... диспетчер местоположений разрешает отложенные обновления только в том случае, если на устройстве доступно оборудование GPS и когда для требуемой точности задано значение kCLLocationAccuracyBest или kCLLocationAccuracyBestForNavigation.

а также

... для свойства distanceFilter диспетчера местоположений должно быть установлено значение kCLDistanceFilterNone.

Я боролся с той же проблемой, и, возможно, я нашел ответ, который решает эту проблему для многих - по крайней мере, он решает мою проблему и получает отложенные обновления, работающие последовательно для меня. Я выполнил все шаги в этом списке и, что бы я ни делал, обновления местоположения не будут откладываться. Мне пришло в голову, что у меня могут быть запущены другие приложения, которые не позволяют системе спать, поэтому я убил все другие приложения в трее многозадачности. Я снова запустил пример приложения и... он сработал! Но история на этом не заканчивается. Я попробовал еще раз чуть позже, и хотя в трее многозадачности не было запущено никаких других приложений, я не смог отложить службы определения местоположения. Затем мне пришло в голову, что у меня на телефоне есть приложение, которое называется "Moves", которое поддерживает жизнь даже после того, как вы убили его вручную. Я не совсем уверен, как Moves волшебным образом возвращается к жизни, когда вы его убиваете, но это происходит (возможно, с использованием Bluetooth и службы сохранения / восстановления приложений). Даже если он жив и отслеживает ваше местоположение, он не появляется в трее многозадачности. Я думаю, что только приложения, которые запускаются вручную, появляются в трее - если ОС запускает приложение, оно не появляется в трее. Но я отвлекся... Я смог заставить отложенные службы определения местоположения работать последовательно в моем приложении, запретив Moves использовать службы определения местоположения. Когда я это сделал, Мовс пожаловался, хотя его не было в многозадачном трее. Кажется, что если другое приложение использует службы определения местоположения (и не откладывает), ваше приложение также не будет откладывать.

Привет недавно, когда вышла начальная версия iOS 9 GM, я видел обновление местоположения (allowDeferredLocationUpdatesUntilTraveled:timeout:) не откладывается. Тот же код, используемый для работы в iOS 8.4 и более поздних версиях. Он разряжает аккумулятор моего устройства с огромным запасом.

Что-нибудь нужно явно указать или упомянуть для iOS 9? Не нашел ничего из документации Apple

Вот код, который я реализовал.

- (void) locationManager: (CLLocationManager *) менеджер didUpdateLocations:(NSArray *) местоположения {

if (! self.deferringUpdates) {

[self.locationManager allowDeferredLocationUpdatesUntilTraveled: CLLocationDistanceMax timeout: 30]; self.deferringUpdates = YES; }}

- (void) locationManager: (CLLocationManager *) manager didFinishDeferredUpdatesWithError: (NSError *) error {// Остановить отложенные обновления self.deferringUpdates = NO;

}

Я также установил свойство allowBackgroundLocationUpdates, но даже это не помогло. self.locationManager.allowsBackgroundLocationUpdates= ДА;

В iOS 9 и более поздних версиях, независимо от цели развертывания, вы также должны установить для allowBackgroundLocationUpdates property объекта диспетчера местоположения значение YES, чтобы получать фоновые обновления местоположения. По умолчанию это свойство имеет значение NO, и оно должно оставаться таким до тех пор, пока ваше приложение активно не требует фоновых обновлений местоположения.

https://developer.apple.com/library/prerelease/ios/documentation/Performance/Conceptual/EnergyGuide-iOS/LocationBestPractices.html

Пожалуйста, дайте мне знать, что еще мне нужно сделать

Спасибо

Другие вопросы по тегам