StartUpdateLocations en Background, didUpdatingToLocation solo se llama 10-20 veces

Dispositivo de prueba: iPhone 5 (iOS 7)

Tengo una aplicación que usa RegionMonitoring y updateLocation . Si se ingresa una región, didEnterRegion se llama como se esperaba. Entonces llamo a startUpdatingLocation . Pero el método didUpdateToLocation solo se llama 10-20 veces, mientras que debería actualizar la ubicación hasta que se dispara el temporizador.

El código relevante:

 CLLocationManager *_locationManager; NSTimer *_timer; -(void)initLocationManager { _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; [_locationManager setActivityType:CLActivityTypeOther]; [_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation]; [_locationManager setPausesLocationUpdatesAutomatically:NO]; [_locationManager setDistanceFilter:kCLDistanceFilterNone]; } //Did Enter Region, called as expected: - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { [_locationManager startUpdatingLocation]; _timer = [NSTimer scheduledTimerWithTimeInterval:300.0f target:self selector:@selector(scheduleMethod:) userInfo:nil repeats:NO]; } //Timer Fire Method: - (void) scheduleMethod:(NSTimer*)timer { [Utils writeToLog:@"Timer-Stop"]; [_locationManager stopUpdatingLocation]; } //This Method only called 10-20 Times (in the first 10-20 Seconds) and not the complete 5 Minutes: - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { [Utils writeToLog:@"LocationUpdate!"]; } 

Hasta ahora he intentado: reiniciar las actualizaciones en el método locationManagerDidPauseLocationUpdates , pero parece que nunca se llamará esto:

 -(void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager { [WRUtils writeToLog:@"LocationUpdate paused, restarted"]; [_locationManager startUpdatingLocation]; } 

Compruebe si hay errores en el método didFailWithError , pero tampoco se llama. Y jugó un poco con las propiedades:

 [_locationManager setActivityType:CLActivityTypeOther]; [_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation]; [_locationManager setPausesLocationUpdatesAutomatically:NO]; 

La configuración de Plist es correcta, supongo: Modos de fondo requeridos SÍ Fondo requerido Modos Elemento 0 Registros de aplicación para actualizaciones de ubicación

¿Como puedo resolver esto?

Apple ha introducido una nueva política en iOS 7. iOS 7 ya no ofrece actualizaciones de ubicación en segundo plano si llama “startUpdatingLocation” mientras la aplicación está en segundo plano. Solo obtiene la actualización cuando la aplicación se pone en primer plano en este caso.

Cuando usa la función geofencing, su aplicación solo obtiene unos segundos cada vez que recibe una notificación RegionEntered / Exited para procesar esta notificación. Y en estos pocos segundos también puede obtener actualizaciones de ubicación. Luego de estos pocos segundos, iOS 7 solo suspende tu aplicación nuevamente.

Puede usar la tarea en segundo plano para obtener más de unos pocos segundos, pero en iOS 7, Apple también ha reducido el tiempo que las aplicaciones pueden ejecutarse en segundo plano de 10 minutos (iOS 6 en adelante) a solo 3 minutos en iOS 7. Parece que estos 3 minutos son la cantidad total durante todo el tiempo que la aplicación está en segundo plano. Lo que significa que no puedes solicitar iOS 7 10 veces para obtener 1 minuto de fondo, solo obtendrás 3 minutos en total, por lo tanto, después de la 3ª vez que hayas pedido un minuto, tu aplicación ya no tendrá ningún fondo. en absoluto.

Su única posibilidad de obtener actualizaciones de ubicación en segundo plano es llamar a “startUpdatingLocation” mientras la aplicación está en primer plano. Esto es triste especialmente cuando solo necesita actualizaciones de ubicación en respuesta a la región (mensajes de entrada / salida, porque necesita dejar que las actualizaciones de ubicación funcionen todo el tiempo. Pero al menos puede reducir el uso de la batería estableciendo el valor de precisión en kCLLocationAccuracyThreeKilometers cuando no necesita actualizaciones de ubicación y establece la precisión de kCLLocationAccuracyBest solo cuando realmente necesita las coordenadas geográficas. El iOS no activará el GPS para el valor kCLLocationAccuracyThreeKilometers, por lo que el uso de la batería sería moderado en este caso.

Además, el valor kCLLocationAccuracyBestForNavigation para la precisión parece causar problemas en el IOS 7. No obtengo ninguna actualización de ubicación con este valor si el dispositivo no está conectado a una fuente de alimentación externa.

En general, la nueva política de iOS 7 para actualizaciones de ubicación hace que sea mucho más difícil desarrollar ciertos tipos de aplicaciones. En lugar de registrarse para obtener actualizaciones de ubicación solo cuando sea necesario, se ve obligado a registrarse durante el tiempo de vida de su aplicación. Lo que, por supuesto, agota la batería un poco más rápido, aunque la intención de Apple para esta nueva política fue probablemente la contraria.

ACTUALIZAR:

Después de algunas pruebas más, he encontrado algún tipo de solución para el problema. Los documentos de Apple mencionan que cuando se utiliza la API de cambio de ubicación significativa, las aplicaciones pueden recibir actualizaciones de ubicación en segundo plano, incluso si “startUpdatingLocation” se inicia en segundo plano.

Mis primeras pruebas no funcionaron bien. Estaba registrando mi aplicación para actualizaciones de ubicación significativas dentro de la región supervisando los métodos de delegado justo antes de llamar a StartUpdatingLocation (por lo que este servicio de ubicación solo está habilitado cuando es necesario), pero esto aún no ofrece actualizaciones de ubicación en segundo plano como sugieren los documentos.

Pero si comienza a escuchar cambios significativos de ubicación directamente después de que se inicie su aplicación (y nunca la apague), puede llamar a start “startUpdatingLocation” mientras la aplicación está en segundo plano y también recibir actualizaciones de ubicación en segundo plano. El uso de la batería de tener la característica de “cambio de ubicación significativo” todo el tiempo parece ser muy baja, por lo que esta será probablemente la solución para la mayoría de las aplicaciones.

Debe verificar si la función “cambio de ubicación significativo” está disponible en el dispositivo, pero parece que todos los dispositivos actuales sí lo admiten. Incluso la 5ª generación de iPod Touch lo admite (el iPod Touch no puede usar torres de celulares para actualizaciones de ubicación, que es el método básico de esta función de acuerdo con los documentos de Apple, así que supongo que podemos suponer que todos los dispositivos actuales con iOS 7 puede usar la API de “actualización de ubicación significativa.” Aunque probablemente sea una buena idea verificar si esta función está realmente disponible, tal vez haya ciertas circunstancias en que la función no esté disponible).

Usar la API de “cambio de ubicación significativo” podría tener una desventaja: la aplicación puede iniciarse en segundo plano (si fue terminada en segundo plano por iOS para reutilizar su memoria para otras aplicaciones) repetidamente e innecesariamente cada vez que el dispositivo se haya movido “significativamente “(Según los documentos: cuando la torre celular ha cambiado, pero no más de una vez cada 5 minutos). Por lo tanto, se lanzarán las aplicaciones que solo necesitan activarse cuando se salga o ingrese una determinada región, y se informará sobre la ubicación cambiada todo el tiempo, no solo en esas regiones. Pero supongo que esto debería ser mucho mejor que tener las actualizaciones de ubicación estándar activas todo el tiempo.

Mi iPhone 5s drena la batería solo el 1% durante la noche con los importantes cambios de ubicación activos, en lugar del 12% con las actualizaciones de ubicación estándar activas con la precisión establecida en 3 km.

Espero que esto ayude a todos los desarrolladores que están luchando con el nuevo comportamiento de iOS 7.

En segundo plano no se ejecutará el temporizador, por lo tanto, aquí el objeto del temporizador no responderá, debe crear el manejador de tareas en segundo plano, consultar el comentario del siguiente enlace,

¿Cómo ejecutar el temporizador en el fondo de la aplicación?

En segundo plano si desea continuar con el servicio de ubicación, debe configurar pausesLocationUpdatesAutomaticamente marcar, marcar información en

pausesLocationUpdatesInformación de marca automática

  if ([self.locationManager respondsToSelector:@selector(pausesLocationUpdatesAutomatically)]) { self.locationManager.pausesLocationUpdatesAutomatically = NO; } 

verifique mi comentario sobre el servicio de ubicación yendo al estado “Inactivo” en iPhone 5

Para el administrador de ubicación a continuación se encuentran los métodos CLLocationManagerDelegate para la actualización de la ubicación,

  - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation [Deprecated in __IPHONE_6_0] - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0); 

Donde encontraste

  - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation ?? 

Use el código siguiente en su método didEnterRegion para iniciar actualizaciones nuevamente

 [_locationManager startMonitoringSignificantLocationChanges]; if ([_locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { _locationManager.allowsBackgroundLocationUpdates =YES; } [_locationManager startUpdatingLocation];