Actualización continua de la ubicación en segundo plano iOS13

9

Actualmente estoy probando el modo de ubicación en segundo plano en iOS 13, ya que quiero seguir la ubicación y el movimiento del usuario (usando el CMMotionManager) en segundo plano. Por lo tanto, tengo mi propia clase (singleton) que maneja el seguimiento de ubicación. Inicializo CLLocationManager de la siguiente manera:

    func initializeLocationManager() -> CLLocationManager {
        let manager = locationManager ?? CLLocationManager()
        manager.delegate = self
        manager.requestAlwaysAuthorization()
        manager.allowsBackgroundLocationUpdates = true
        manager.pausesLocationUpdatesAutomatically = false
        manager.distanceFilter = kCLDistanceFilterNone
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.activityType = .other
        return manager
    }

Entonces comienzo los siguientes servicios:

   func startLocationServices() {
        // ...
        locationManager.startUpdatingLocation()
        locationManager.startMonitoringVisits()
        locationManager.startMonitoringSignificantLocationChanges()
        // ...
    }

Además, implementé los métodos CLLocationManagerDelegate-didChangeAuthorization (), didUpdateLocation ().

En el archivo info.plist agregué las siguientes entradas:

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>...</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>...</string>
<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array> 

En mi ViewController, llamo a startLocationServices. Actualmente, configuro la autorización de la aplicación para rastrear los datos de ubicación en ".authorizedAlways"

Las actualizaciones de ubicación se detienen después de aproximadamente 60 - 130 minutos.

Para resolver el problema, ya agregué la función didFinishLaunchingWithOptions, que activa las actualizaciones de ubicación nuevamente:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    if let launchOptions = launchOptions,
        let isLocationKey = launchOptions[UIApplication.LaunchOptionsKey.location] as? Bool,
        isLocationKey {
        restartServices()

    }
    return true
} 

Cuando la aplicación se despertó usando esta función, logré obtener datos continuos en algunas pruebas, pero a veces la aplicación se suspendió nuevamente después de unos minutos.

Por último, también probé un temporizador que reinicia el seguimiento de ubicación cada 5 minutos, pero esto no parece afectar en absoluto la duración de la actualización.

Entonces, mi pregunta es si hay una forma de recibir continuamente las actualizaciones de ubicación en segundo plano, o ¿hay alguna opción que me falta?

Gracias por adelantado.

Editar: probé la aplicación en iOS 12 y obtiene actualizaciones continuas en 5/5 pruebas. Así que supongo que el problema está relacionado con iOS 13.

Mattll
fuente
1
Oye, ¿obtuviste la solución para esto?
Abhishek
2
Bueno, como se indicó en mi último comentario, podría aumentar drásticamente la duración antes de que la aplicación se mueva al estado suspendido, reduciendo los recursos consumidos en segundo plano. -> Eliminé la colección de movimiento completamente de la aplicación. -> Al pasar al fondo disminuyo la precisión y aumento la distancia Filtrar para que las ubicaciones obtengan menos eventos, detengo algunas tareas que actualizan la interfaz de usuario, reduzco la recopilación de otras fuentes de datos, no exporto mis datos en segundo plano u otra carga de trabajo. Así que ahora tengo alrededor de 3000 minutos en segundo plano.
Mattll
¿me pueden ayudar con un código?
Abhishek
1
En su AppDelegate.swift, implemente las funciones func applicationDidEnterBackground (_ application: UIApplication) y func applicationDidEnterBackground (_ application: UIApplication). En esas funciones acceda a su CLLocationManager y establezca las propiedades distanceFilter, deseadaAccuracy en consecuencia. También disminuyo la muestra de mi temporizador que uso para escribir alguna información de uso (como el estado actual de la batería) y finalizo un temporizador que uso para actualizar periódicamente la vista principal o viceversa cuando el método applicationDidBecomeActive. Supongo que jugar y probar es la clave.
Mattll

Respuestas:

1

¡Nada está mal con el código! , Me he enfrentado al mismo problema y después de la investigación descubrí que

En la conferencia magistral de WWDC19, Apple anunció dos cambios en la forma en que funcionarán los permisos de ubicación en iOS 13. El primer cambio brinda a los usuarios la opción de compartir su ubicación con su aplicación solo una vez. Esto hace que sea más fácil probar las características de ubicación y ayuda a los usuarios a mantener privados los datos confidenciales de ubicación.

El primer cambio notable es que, incluso cuando llame requestAlwaysAuthorization, el usuario solo obtendrá las opciones 'justo ahora' y 'cuando esté en uso' en el cuadro de diálogo de permisos. Si el usuario le otorga el permiso "cuando está en uso" e intenta buscar una ubicación en segundo plano, solo entonces se le presentará un cuadro de diálogo para otorgar el permiso de fondo.

Por eso, cuando las subvenciones usuario WhenInUseUsage de permiso que obtendrán alwaysen CLAuthorizationStatusy Si el usuario elige Allow Once CLAuthorizationStatusserán descansado a notDeterminedla vez lanza una aplicación de nuevo

Puede consultar este artículo para obtener información detallada https://medium.com/q42-engineering/apple-location-permission-ios13-1e0e59002889

Y aquí está el video https://developer.apple.com/videos/play/wwdc2019/705/

EDITAR

Después, cuando en el usuario, el permiso otorgado por el usuario iOS mostrará al usuario otro diálogo después de algunos días para cambiar el permiso de cuando está en uso para permitir siempre.

Por lo tanto, ahora no hay forma de pedirle directamente al usuario que siempre permita el permiso instantáneamente como lo hicimos antes.

ingrese la descripción de la imagen aquí

Prashant Tukadiya
fuente
1
¿Eso resolvió tu problema? Establecí manualmente el nivel de autorización para siempre en -> Configuración -> Privacidad -> Servicios de ubicación Pero eso no resolvió el problema.
Mattll
1
Pero incluso después de establecer el indicador de permitir siempre, la aplicación finalizará en algún momento. ¿Tu aplicación se ejecuta continuamente después?
Mattll
1
Gracias por la actualización. Ya encontré esa ventana emergente, y también puedes configurar las notificaciones siempre en la configuración de privacidad del iPhone, pero esto no resuelve el problema anterior para mí. En iOS 12 todavía no encontré ningún problema con el seguimiento continuo de la ubicación, mientras que en iOS 13 la aplicación se suspende después de un tiempo.
Mattll
1
Aquí están mis observaciones después de explorar el problema durante algún tiempo. En pocas palabras: cuanto menos hago mientras estoy en segundo plano, más tiempo puedo grabar hasta la suspensión. Inhabilité la mayor parte de la funcionalidad que se ejecutó en segundo plano, por lo que por ahora solo hago un seguimiento de la información de ubicación / uso y la almaceno utilizando datos centrales. Además, cuando la aplicación entra en modo de fondo, cambio el distanceFilter y la precisión deseada del administrador de ubicación. Ahora, puedo rastrear alrededor de 3000 sin ser suspendido.
Mattll
1
¿Alguien tiene esta solución?
Abhishek