Estoy escribiendo una aplicación que requiere actualizaciones de ubicación en segundo plano con alta precisión y baja frecuencia . La solución parece ser una tarea NSTimer en segundo plano que inicia las actualizaciones del administrador de ubicación, que luego se apaga inmediatamente. Esta pregunta se ha hecho antes:
Obtener la ubicación del usuario cada n minutos después de que la aplicación pasa a segundo plano
iOS No es el problema típico del temporizador de seguimiento de ubicación en segundo plano
Temporizador de fondo de larga duración de iOS con modo de fondo de "ubicación"
Servicio en segundo plano de tiempo completo de iOS basado en el seguimiento de la ubicación
pero todavía tengo que conseguir un ejemplo mínimo que funcione. Después de probar cada permutación de las respuestas aceptadas anteriores, armé un punto de partida. Ingresando antecedentes:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"ending background task");
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}];
self.timer = [NSTimer scheduledTimerWithTimeInterval:60
target:self.locationManager
selector:@selector(startUpdatingLocation)
userInfo:nil
repeats:YES];
}
y el método delegado:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(@"%@", newLocation);
NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
[self.locationManager stopUpdatingLocation];
}
El comportamiento actual es que se backgroundTimeRemaining
reduce de 180 segundos a cero (mientras se registra la ubicación), y luego se ejecuta el controlador de vencimiento y no se generan más actualizaciones de ubicación. ¿Cómo modifico el código anterior para recibir actualizaciones periódicas de ubicación en segundo plano de forma indefinida ?
Actualización : estoy apuntando a iOS 7 y parece haber alguna evidencia de que las tareas en segundo plano se comportan de manera diferente:
Inicie el Administrador de ubicaciones en iOS 7 desde la tarea en segundo plano
Respuestas:
Parece que eso
stopUpdatingLocation
es lo que activa el temporizador de vigilancia en segundo plano, así que lo reemplacédidUpdateLocation
con:que parece apagar efectivamente el GPS. El selector para el fondo
NSTimer
se convierte en:Todo lo que hago es alternar periódicamente la precisión para obtener una coordenada de alta precisión cada pocos minutos y, como
locationManager
no se ha detenido,backgroundTimeRemaining
permanece en su valor máximo. Esto redujo el consumo de batería de ~ 10% por hora (con constantekCLLocationAccuracyBest
en segundo plano) a ~ 2% por hora en mi dispositivo.fuente
Escribí una aplicación usando los servicios de ubicación, la aplicación debe enviar la ubicación cada 10 segundos. Y funcionó muy bien.
Simplemente use el método " allowDeferredLocationUpdatesUntilTraveled: timeout ", siguiendo el documento de Apple.
Los pasos son los siguientes:
Obligatorio: registre el modo de fondo para actualizar la ubicación.
1. Crea LocationManger y startUpdatingLocation, con precisión y FilterDistance como lo que quieras:
2. Para que la aplicación se ejecute para siempre con el método "allowDeferredLocationUpdatesUntilTraveled: timeout" en segundo plano, debe reiniciar updateLocation con un nuevo parámetro cuando la aplicación pasa a segundo plano, así:
3. La aplicación obtiene updatedLocations como de costumbre con la devolución de llamada "locationManager: didUpdateLocations:":
4. Pero debe manejar los datos en la devolución de llamada "locationManager: didFinishDeferredUpdatesWithError:" para su propósito
5. NOTA: Creo que deberíamos restablecer los parámetros de LocationManager cada vez que la aplicación cambia entre el modo de fondo / primer plano.
fuente
allowsBackgroundLocationUpdates = YES
yrequestAlwaysAuthorization
orequestWhenInUseAuthorization
. Por ejemplo: `CLLocationManager * locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.allowsBackgroundLocationUpdates = YES; [locationManager requestAlwaysAuthorization]; [locationManager startUpdatingLocation]; `Si tiene
UIBackgroundModes
en su plist conlocation
clave, entonces no necesita usar elbeginBackgroundTaskWithExpirationHandler
método. Eso es redundante. También lo está usando incorrectamente (vea aquí ) pero eso es discutible ya que su plist está configurado.Con
UIBackgroundModes location
el plist, la aplicación seguirá ejecutándose en segundo plano indefinidamente solo mientras seCLLocationManger
esté ejecutando. Si llamasstopUpdatingLocation
mientras está en segundo plano, la aplicación se detendrá y no volverá a comenzar.Tal vez podría llamar
beginBackgroundTaskWithExpirationHandler
justo antes de llamarstopUpdatingLocation
y luego, después de llamarstartUpdatingLocation
, podría llamar alendBackgroundTask
para mantenerlo en segundo plano mientras el GPS está detenido, pero nunca lo intenté, es solo una idea.Otra opción (que no he probado) es mantener el administrador de ubicación en ejecución mientras está en segundo plano, pero una vez que obtenga una ubicación precisa, cambie la
desiredAccuracy
propiedad a 1000 mo más para permitir que el chip GPS se apague (para ahorrar batería). Luego, 10 minutos más tarde, cuando necesite otra actualización de ubicación, cambie la partedesiredAccuracy
posterior a 100 m para encender el GPS hasta que obtenga una ubicación precisa, repita.Cuando llame
startUpdatingLocation
al administrador de ubicación, debe darle tiempo para obtener un puesto. No debe llamar de inmediatostopUpdatingLocation
. Dejamos que se ejecute durante un máximo de 10 segundos o hasta que obtengamos una ubicación de alta precisión sin caché.Debe filtrar las ubicaciones almacenadas en caché y verificar la precisión de la ubicación que obtiene para asegurarse de que cumpla con la precisión mínima requerida (consulte aquí ). La primera actualización que reciba puede tener 10 minutos o 10 días de antigüedad. La primera precisión que obtenga puede ser de 3000 m.
En su lugar, considere usar las API de cambios de ubicación significativos. Una vez que reciba la notificación de cambio significativo, puede comenzar
CLLocationManager
durante unos segundos para obtener una posición de alta precisión. No estoy seguro, nunca he utilizado los servicios de cambio de ubicación significativo.fuente
CoreLocation
referencia de Apple parece recomendar el uso debeginBackgroundTaskWithExpirationHandler
al procesar datos de ubicación en segundo plano: "Si una aplicación de iOS necesita más tiempo para procesar los datos de ubicación, puede solicitar más tiempo de ejecución en segundo plano utilizando el método beginBackgroundTaskWithName: expirationHandler: de la clase UIApplication". - developer.apple.com/library/ios/documentation/UserExperience/…locationManagerDidPauseLocationUpdates
. ¡Verifiqué ese comportamiento 10 veces!Cuando llega el momento de iniciar el servicio de ubicación y detener la tarea en segundo plano, la tarea en segundo plano debe detenerse con un retraso (1 segundo debería ser suficiente). De lo contrario, el servicio de ubicación no se iniciará. Además, el servicio de ubicación debe dejarse encendido durante un par de segundos (por ejemplo, 3 segundos).
Hay un Cocoapod APScheduledLocationManager que permite obtener actualizaciones de ubicación en segundo plano cada n segundos con la precisión de ubicación deseada.
El repositorio también contiene una aplicación de ejemplo escrita en Swift 3.
fuente
¿Qué tal intentarlo con
startMonitoringSignificantLocationChanges:
API? Definitivamente dispara con menos frecuencia y la precisión es razonablemente buena. Además, tiene muchas más ventajas que usar otraslocationManager
API.Ya se ha discutido mucho más sobre esta API en este enlace
fuente
This interface delivers new events only when it detects changes to the device’s associated cell towers
Debe agregar el modo de actualización de ubicación en su aplicación agregando la siguiente clave en su info.plist.
didUpdateToLocation
se llamará al método (incluso cuando su aplicación esté en segundo plano). Puede realizar cualquier cosa sobre la base de esta llamada al métodofuente
Después de iOS 8, hay varios cambios en la recuperación de antecedentes y las actualizaciones relacionadas con el marco CoreLocation realizadas por Apple.
1) Apple introduce la solicitud AlwaysAuthorization para obtener la actualización de ubicación en la aplicación.
2) Apple introduce backgroundLocationupdates para obtener la ubicación desde el fondo en iOS.
Para obtener la ubicación en segundo plano, debe habilitar la Actualización de ubicación en Capacidades de Xcode.
fuente
Para usar los servicios de ubicación estándar mientras la aplicación está en segundo plano, primero debe activar Modos de fondo en la pestaña Capacidades de la configuración de Destino y seleccionar Actualizaciones de ubicación.
O agréguelo directamente a Info.plist .
Entonces necesitas configurar CLLocationManager
C objetivo
Rápido
Ref: https://medium.com/@javedmultani16/location-service-in-the-background-ios-942c89cd99ba
fuente
fuente