StartUpdateLocations en segundo plano, didUpdatingToLocation solo se llama entre 10 y 20 veces.

Dispositivo de testing: iPhone 5 (iOS 7)

Tengo una aplicación que utiliza RegionMonitoring y updateLocation . Si se ingresa una región, didEnterRegion se llama como se esperaba. Luego llamo startUpdatingLocation . Pero el método didUpdateToLocation solo se llama entre 10 y 20 veces, mientras que debe actualizar la location hasta que el timer dispare.

El código relevante:

 CLLocationManager *_locationManager; NSTimer *_timer; -(void)initLocationManager { _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; [_locationManager setActivityType:CLActivityTypeOther]; [_locationManager setDesinetworkingAccuracy: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 esto nunca se llama:

 -(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 properties:

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

Los ajustes de Plist son correctos. Supongo que: Modos de background necesarios. SÍ. Modos de background requeridos. Artículo 0. Registros de aplicaciones para actualizaciones de location.

¿Como puedo resolver esto?

Apple introdujo una nueva política en iOS 7. iOS 7 ya no ofrece actualizaciones de location en segundo plano si llama a "startUpdatingLocation" mientras la aplicación se encuentra en segundo plano. Solo se actualiza cuando la aplicación se pone en primer plano en este caso.

Cuando usa la característica de geofencing, su aplicación solo obtiene unos segundos cada vez que recibe una notificación de RegionEntenetworking / Exited para procesar esta notificación. Y en estos pocos segundos también puede get actualizaciones de location. Después de estos pocos segundos, iOS 7 acaba de suspender su aplicación nuevamente.

Puede utilizar la tarea en segundo plano para get más de unos pocos segundos, pero en iOS 7, Apple también ha networkingucido el time que las aplicaciones pueden ejecutarse en segundo plano desde 10 minutos (iOS 6 y anteriores) a solo 3 minutos con iOS 7. Parece que que estos 3 minutos son la cantidad total durante todo el time que la aplicación está en segundo plano. Lo que significa que no puedes pedir iOS 10 10 veces para get un time de background de 1 minuto, solo obtendrás 3 minutos en total, así que después de la 3ª vez que has pedido un minuto, tu aplicación ya no recibirá más time de background. en absoluto.

Su única oportunidad para get actualizaciones de location en segundo plano es llamar "startUpdatingLocation" mientras la aplicación está en primer plano. Esto es triste, especialmente cuando solo necesita actualizaciones de location en respuesta a la Región (Ingrese / Salga de los posts, porque debe permitir que las actualizaciones de location funcionen todo el time. Pero al less puede networkingucir el uso de la batería al establecer el valor de precisión en kCLLocationAccuracyThreeKilometers cuando no necesita actualizaciones de location y establece la precisión en kCLLocationAccuracyBest solo cuando realmente necesite las coorderadas geo. El iOS no encenderá el GPS para el valor kCLLocationAccuracyThreeKilometers, por lo que el uso de la batería sería moderado en este caso.

También el valor kCLLocationAccuracyBestForNavigation para la precisión parece causar problemas según el IOS 7. No obtengo ninguna actualización de location con este valor si el dispositivo no está conectado a una fuente de alimentación externa.

Con todo, la nueva política de iOS 7 para las actualizaciones de location hace que sea mucho más difícil desarrollar ciertos types de aplicaciones. En lugar de registrarse para actualizaciones de location solo cuando sea necesario, se ve obligado a registrarse para estos durante la vida útil de su aplicación. Lo cual, 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 opuesta.

ACTUALIZAR:

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

Mis primeras testings no funcionaron bien. Estaba registrando mi aplicación para las actualizaciones de location significativas dentro de la región que monitorea los methods de delegado justo antes de llamar a startUpdatingLocation (por lo que este service de location solo se habilita cuando es necesario), pero esto no ofrece actualizaciones de location en segundo plano como sugieren los documentos.

Pero si comienza a escuchar cambios significativos de location directamente después de que su aplicación se inicia (y nunca la apaga), puede llamar al inicio "startUpdatingLocation" mientras la aplicación está en segundo plano y también recibir actualizaciones de location en segundo plano. El uso de la batería de tener la característica de "cambio de location significativo" en todo momento parece ser muy bajo, por lo que esta será probablemente la solución para la mayoría de las aplicaciones.

Debe verificar si la function "cambio significativo de location" está disponible en el dispositivo, pero parece que todos los dispositivos actuales sí lo admiten. Incluso la quinta generación de iPod Touch lo admite (The iPod Touch no puede usar las torres de telefonía mobile para las actualizaciones de location, que es el método base de esta function 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 location significativa". Aunque probablemente sea una buena idea verificar si esta function está realmente disponible, tal vez haya ciertas circunstancias en las que la function no esté disponible).

El uso de la API de "cambio de location significativo" podría tener una desventaja: la aplicación se puede iniciar en segundo plano (si el iOS terminó en segundo plano para reutilizar su memory para otras aplicaciones) de forma repetida e innecesaria siempre que el dispositivo se haya movido "significativamente "(De acuerdo con la documentation: cuando la torre celular ha cambiado, pero no más de una vez cada 5 min). Entonces, las aplicaciones que solo necesitan ser activadas, cuando una región determinada se sale o se ingresa, se lanzarán e informarán sobre la location cambiada todo el time, no solo en esas regiones. Pero supongo que esto debería ser mucho mejor que tener actualizaciones de location estándar activas todo el time.

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

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

En el timer de background no se ejecutará, por lo que aquí el object del timer no responderá, debe crear el controller de tareas de background, verifique el comentario del enlace a continuación,

¿Cómo ejecutar el timer en el background de la aplicación?

En segundo plano, si desea continuar el service de location de lo que necesita para establecer pausesLocationUpdatesAutomatically flag, flag info on

pausesLocationUpdatesAutomatically flag info

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

verifique mi comentario sobre el service de location yendo al estado "Inactivo" en el iPhone 5

Para el administrador de la location, a continuación se encuentran los methods CLLocationManagerDelegate para la actualización de la location,

  - (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 comenzar las actualizaciones nuevamente.

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