Comportamiento para una API de ubicación de cambio significativa cuando finaliza / suspende?

Esta es la sección de la documentación de CLLocationManager que describe el comportamiento de la aplicación con startMonitoringSignificantLocationChanges :

Si inicia este servicio y su aplicación se cancela posteriormente, el sistema relanza automáticamente la aplicación en segundo plano si llega un nuevo evento. En tal caso, el diccionario de opciones transferido a la aplicación: didFinishLaunchingWithOptions: método del delegado de su aplicación contiene la clave UIApplicationLaunchOptionsLocationKey para indicar que su aplicación se inició debido a un evento de ubicación. Al reiniciar, debe configurar un objeto administrador de ubicación y llamar a este método para continuar recibiendo eventos de ubicación. Cuando reinicia los servicios de ubicación, el evento actual se entrega a su delegado de inmediato. Además, la propiedad de ubicación de su objeto de administrador de ubicación se completa con el objeto de ubicación más reciente, incluso antes de comenzar los servicios de ubicación.

Por lo tanto, entiendo que si su aplicación finaliza (y asumo que si no llama a stopMonitoringSignificantLocationChanges desde applicationWillTerminate ) se despertará con un parámetro UIApplicationLaunchOptionsLocationKey para la aplicación: didFinishLaunchingWithOptions . En ese momento, crea su CLLocationManager , llame a startMonitoringSignificantLocationChanges y realice el procesamiento de su ubicación en segundo plano durante un tiempo limitado . Así que estoy bien con este bit.

El párrafo anterior solo habla de lo que sucede cuando se termina la aplicación, no sugiere lo que haces cuando la aplicación se suspende. La documentación para didFinishLaunchingWithOptions dice:

La aplicación rastrea las actualizaciones de ubicación en el fondo, se purgó y ahora se relanzó. En este caso, el diccionario contiene una clave que indica que la aplicación se relanzó debido a un nuevo evento de ubicación.

Te sugerimos que solo recibirás esta llamada cuando se lance tu aplicación (debido a un cambio de ubicación) después de que hayas terminado.

Sin embargo, el párrafo sobre el Servicio de Cambio Significativo en la Guía de Progtwigción de Conocimiento de Ubicación tiene lo siguiente para decir:

Si deja este servicio en ejecución y su aplicación se suspende o cancela posteriormente, el servicio automáticamente activará su aplicación cuando lleguen nuevos datos de ubicación. En el momento del despertar, su aplicación se pone en segundo plano y se le da una pequeña cantidad de tiempo para procesar los datos de ubicación. Debido a que su aplicación está en segundo plano, debe hacer un trabajo mínimo y evitar cualquier tarea (como consultar la red) que pueda evitar que vuelva antes de que expire el tiempo asignado. Si no lo hace, su aplicación puede ser cancelada.

Esto sugiere que te despiertan los datos de ubicación si tu aplicación se ha suspendido, pero no menciona cómo te despiertan:

  • ¿El UIApplicationDelegate recibe una callback diciéndome que estoy reanudando desde un estado suspendido a un estado de fondo?
  • ¿El administrador de la ubicación (que estaba congelado cuando se suspendió la aplicación) comienza a recibir locationManager: didUpdateToLocation: fromLocation callbacks?
  • ¿Solo necesito implementar código en mi mensaje didUpdateToLocation que comprueba el estado de la aplicación y realiza un procesamiento mínimo si está en modo de fondo?

En el proceso de escribir esto, creo que acabo de responder a mi propia pregunta, pero sería genial que mi comprensión de esto sea confirmada por alguien con más conocimiento.

Desde que formulé esta pregunta, hice un buen número de pruebas (principalmente en el tren entre el hogar y el trabajo) y confirmé que el comportamiento de las aplicaciones suspendidas es el que sospechaba al final de la pregunta.

Es decir, su aplicación suspendida se activa, no recibe ninguna callback en el delegado de su aplicación, en su lugar recibe las actualizaciones de su ubicación a través de su CLLocationManagerDelegate existente. Puede detectar que se está ejecutando en segundo plano al verificar el estado de la aplicación y hacer un trabajo limitado para el caso en que se lo despierte de un estado suspendido para realizar el procesamiento de la ubicación.

[UIApplication sharedApplication].applicationState == UIApplicationStateBackground 

Llegué a esta conclusión con un arnés de prueba de ubicación que puede descargar y probar. Es una aplicación bastante simple que le permite activar cambios significativos y API de cambio de GPS a través de la IU y registrar todas las respuestas que recibe.

Nota: El punto seis en la respuesta anterior no es correcto. Las aplicaciones congeladas y secas reciben las devoluciones de llamada de CLLocationManagerDelegate cuando se despiertan desde un estado suspendido.

Mi comprensión es la siguiente (estoy en el proceso de escribir una aplicación que se basa en esta API, pero no he completado este componente lo suficiente como para comenzar a probar):

  1. Su aplicación se ejecuta por primera vez, se registra en startMonitoringSignificantLocationChanges y proporciona una función de callback. Mientras su aplicación se está ejecutando, llamará a esa callback siempre que reciba un cambio significativo.
  2. Si su aplicación se pone en segundo plano, UIApplication recibirá applicationWillResignActive , seguido de applicationDidEnterBackground .
  3. Si se mata su aplicación mientras está suspendida en segundo plano, no se le notificará; sin embargo, si se mata su aplicación mientras se está ejecutando (en primer plano o en segundo plano, que yo sepa), obtendrá un momento con la aplicaciónWillTerminate . No puede solicitar tiempo de fondo adicional desde esta función.
  4. A pesar de haber sido asesinado en segundo plano, el SO relanzará tu aplicación. Si el SO simplemente lanza su aplicación para un cambio, recibirá una llamada a la aplicación didFinishLaunchingWithOptions :

     if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) 

    lo ayudará a determinar si ha regresado de un cambio de ubicación de fondo.

  5. Si, en cambio, se estaba ejecutando en segundo plano, y el usuario relanzó manualmente su aplicación, recibirá una aplicación WillEnterForeground seguida de applicationDidBecomeActive .
  6. Independientemente de cómo sucedió, cuando se relanza la aplicación (a menos que todavía se esté ejecutando en segundo plano como resultado de una tarea en segundo plano y dicha tarea haya comenzado a supervisar los cambios), debe indicar explícitamente a startMonitoringSignificantLocationChanges nuevamente porque la callback no es más unida después de “liofilización”. Y sí, solo necesita implementar el código en didUpdateToLocation una vez que haya vuelto a conectar un controlador de ubicación de algún tipo una vez que regrese del estado suspendido.

Esto es lo que estoy haciendo con mi desarrollo de código en este momento. Como mencioné antes, no estoy listo para probar esto en un dispositivo, así que no puedo decir si lo he interpretado todo correctamente, por lo que los comentaristas, pueden corregirme (aunque he leído mucho en el tema).

Ah, y si por un golpe de mala suerte lanzas una aplicación que hace lo que yo quiero que haga la mía, podría llorar 🙂

¡Buena suerte!

Si la aplicación se evoca desde un estado suspendido como resultado de la aplicación de cambio de ubicación se iniciará en estado de fondo.

Todos los objetos estarán en vivo y recibirá la actualización de la ubicación en el delegado existente.