¿Comportamiento de la API de ubicación de cambio significativo cuando se cancela / suspende?

108

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 reinicia automáticamente la aplicación en segundo plano si llega un nuevo evento. En tal caso, el diccionario de opciones pasado 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 de 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 envía 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 iniciar los servicios de ubicación.

Entonces, tengo entendido que si su aplicación termina (y supongo que si no llama a stopMonitoringSignificantLocationChanges desde applicationWillTerminate ), se despertará con un parámetro UIApplicationLaunchOptionsLocationKey a la aplicación: didFinishLaunchingWithOptions . En ese momento, crea su CLLocationManager , llama a startMonitoringSignificantLocationChanges y realiza el procesamiento de la ubicación en segundo plano durante un tiempo limitado . Así que estoy bien con esta parte.

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

La aplicación rastrea las actualizaciones de ubicación en segundo plano, se eliminó y ahora se ha relanzado. En este caso, el diccionario contiene una clave que indica que la aplicación se reinició debido a un nuevo evento de ubicación.

Sugerir que solo recibirá esta llamada cuando se inicie su aplicación (debido a un cambio de ubicación) después de que haya sido cancelado.

Sin embargo, el párrafo sobre el Servicio de cambio significativo en la Guía de programación de reconocimiento de ubicación tiene lo siguiente que decir:

Si deja este servicio en ejecución y su aplicación se suspende o finaliza posteriormente, el servicio activa automáticamente su aplicación cuando llegan nuevos datos de ubicación. Al despertar, su aplicación se coloca en segundo plano y se le da un poco de tiempo para procesar los datos de ubicación. Debido a que su aplicación está en segundo plano, debe realizar un trabajo mínimo y evitar cualquier tarea (como consultar la red) que pueda evitar que regrese antes de que expire el tiempo asignado. Si no es así, su solicitud puede ser cancelada.

Esto sugiere que se le ha despertado con datos de ubicación si su aplicación ha sido suspendida, pero no menciona cómo se le ha despertado:

  • ¿El UIApplicationDelegate recibe una devolución de llamada que me dice que estoy reanudando desde un estado suspendido a un estado de fondo?
  • ¿El administrador de ubicación (que se secó por congelación cuando se suspendió la aplicación) comienza a recibir devoluciones de llamada de locationManager: didUpdateToLocation: fromLocation ?
  • ¿Solo necesito implementar código en mi mensaje didUpdateToLocation que verifica el estado de la aplicación y realiza un procesamiento mínimo si está en modo de fondo?

En el proceso de redacción de esto, creo que acabo de responder mi propia pregunta, pero sería genial que alguien más conocedor confirmara mi comprensión de esto.

RojoAzulCosa
fuente

Respuestas:

80

Desde que hice esta pregunta, he realizado algunas pruebas (principalmente en el tren entre la casa y el trabajo) y he confirmado 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 devolución de llamada en el delegado de su aplicación, sino que recibe actualizaciones de su ubicación a través de su CLLocationManagerDelegate existente . Puede detectar que está ejecutando en segundo plano al verificar el estado de la aplicación , y hacer un trabajo limitado para el caso en el que lo despierten de un estado suspendido para realizar el procesamiento de 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 interfaz de usuario y registrar todas las respuestas que recibe.

NB El punto seis de la respuesta anterior no es correcto. Las aplicaciones suspendidas liofilizadas reciben devoluciones de llamada CLLocationManagerDelegate cuando se despiertan de un estado suspendido.

RojoAzulCosa
fuente
1
Marque el número 6 en mi respuesta para no confundir a la gente.
Aaron
Irónicamente, también sentí la misma confusión al desarrollarme para el cambio significativo. Todavía tengo algunas dudas sobre lo que sucede si se cierra la aplicación. ¿La devolución de llamada UIApplicationDelegate no sucederá? es la forma correcta de iniciar la aplicación. Si el administrador de ubicación aún no se ha activado, ¿cómo puede recibir las notificaciones en segundo plano? (tiempo para más investigación y desarrollo)
darshansonde
Muchas gracias por la aplicación de muestra, fue muy útil para mí. Tengo una pregunta: ¿Qué pasa si estuviera usando el servicio de ubicación estándar en segundo plano, no el más importante? ¿La aplicación también se reiniciará después de la terminación en ese caso? Hice esta pregunta aquí en detalle, me alegraría si pudiera
aclararme
2
No funcionó en ios7 stackoverflow.com/questions/18946881/…
Igor
¿Sabe cuánto tiempo tardó en cerrarse su aplicación? ¿Y luego obtener una devolución de llamada de appDelegate en su lugar? (¿Son como 30 minutos? ¿2 horas? ¿5 horas?) La razón por la que pregunto esto es porque he configurado una región para monitorear. Intenté muchas veces que mi aplicación se iniciara, pero solo una vez logré reiniciar la aplicación. Las otras veces la didExitRegiondevolución de llamada, pero no pude hacerlo startLocationUpdatesdesde allí, ya que no fue a través del lanzamiento de la aplicación ...
Cariño
25

Mi comprensión es la siguiente (estoy en el proceso de escribir una aplicación que se base 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 devolución de llamada. Mientras su aplicación se está ejecutando, llamará a esa devolución de llamada cada vez que reciba un cambio significativo.
  2. Si su aplicación se coloca en segundo plano, UIApplication recibirá applicationWillResignActive , seguido de applicationDidEnterBackground .
  3. Si su aplicación es eliminada mientras está suspendida en segundo plano, no se le notificará; sin embargo, si su aplicación se mata mientras se está ejecutando (en primer plano o en segundo plano que yo sepa), obtendrá un momento con applicationWillTerminate . No puede solicitar tiempo de fondo adicional desde esta función.
  4. A pesar de haber sido eliminado en segundo plano, el sistema operativo reiniciará su aplicación. Si el sistema operativo simplemente inicia su aplicación para variar, recibirá una llamada a la aplicación didFinishLaunchingWithOptions :

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])

    le ayudará a determinar si ha regresado de un cambio de ubicación en segundo plano.

  5. Si, en cambio, se estaba ejecutando en segundo plano y el usuario reinicia manualmente su aplicación, recibirá un applicationWillEnterForeground seguido de applicationDidBecomeActive .
  6. Independientemente de cómo sucedió, cuando se reinicia su 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 monitorear los cambios), debe decirle explícitamente que inicieMonitoringSignificantLocationChanges nuevamente porque la devolución de llamada es no más tiempo adjunto después de "secado por congelación". Y sí, solo necesita implementar código en didUpdateToLocation una vez que haya vuelto a adjuntar un controlador de ubicación de algún tipo una vez que regrese del estado suspendido.

Esto es lo que estoy haciendo con el desarrollo de mi código en este momento. Como mencioné antes, no estoy listo para probar esto en un dispositivo, por lo que no puedo decir si he interpretado todo correctamente, por lo que los comentaristas, no duden en corregirme (aunque he hecho una lectura sustancial sobre 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!

Aaron
fuente
1
@Tegeril +1 Gracias por la respuesta. Estaba empezando a escuchar grillos en este. :) Me sorprende que las aplicaciones que comenzaron a ser suspendidas necesiten volver a llamar a startMonitoringSignificantLocationChanges. ¿Tiene un enlace al documento donde se describe esto? Según tenía entendido, la carga desde un estado suspendido creará una instancia de todos sus objetos tal como estaban cuando se suspendió la aplicación. Por lo tanto, esperaría que la solicitud de cambio significativo esté en vigor.
RedBlueThing
¿Podrías estar hablando de esto? "Al reiniciar, debe configurar un objeto de administrador de ubicación y llamar a este método para continuar recibiendo eventos de ubicación". Pero creo que esto se refiere al caso en el que su aplicación se inició desde un estado finalizado (por un evento de ubicación). Esta es básicamente la raíz de mi pregunta, '¿qué sucede con el caso suspendido?'.
RedBlueThing
Morgan Grainger en los foros de desarrollo sugirió esto: "Necesita crear un CLLocationManager, configurar un delegado y llamar a startMonitoringSignificantLocationChanges cuando se inicie su aplicación, de lo contrario, la ubicación principal no tendrá dónde entregar las actualizaciones". en el contexto de reiniciar una aplicación independientemente de si se encuentra en un estado finalizado o suspendido. Desde "la aplicación se relanzó después de startMonitoringSignificantLocationChanges y ¿ahora qué?"
Aaron
Estoy de acuerdo en que esto aún podría ser vago incluso en el contexto de esa publicación del foro (el póster estaba discutiendo el despertar desde el fondo, pero Morgan usó el reinicio más general de una aplicación). Sigo pensando que debe llamar para monitorear nuevamente cuando su aplicación se reinicie si desea trabajar con la función de cambios significativos. Si, en cambio, desea iniciar una tarea en segundo plano y actualizar con el servicio de ubicación estándar y la funcionalidad GPS, esa es una opción alternativa. Sin embargo, no creo que deba volver a registrarse en cada lanzamiento con cambios significativos para poder lanzarlo nuevamente.
Aaron
1
Me alegro de que saliera algo definitivo de esto, debería ayudarme en el futuro :)
Aaron
1

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

Todos los objetos estarán activos y recibirás una actualización de ubicación en el delegado existente.

Anshu
fuente