iOS Geofence CLCircularRegion monitoring. locationManager: didExitRegion no parece funcionar como se esperaba
core-location cllocationmanager (9)
Actualmente estoy tratando de hacer que mi aplicación monitoree regiones particulares usando CoreLocation
sin embargo, estoy descubriendo que no parece funcionar como se esperaba, me parece que no puede funcionar con un radio pequeño y pequeño establecido para cada ubicación, es decir, 10 m.
También armé una pequeña aplicación de prueba que traza el radio del círculo en un mapa para que pueda ver visualmente lo que está sucediendo.
El código que estoy usando para monitorear ubicaciones es el siguiente:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Set-up a region
CLLocationDegrees latitude = 52.64915;
CLLocationDegrees longitude = -1.1506367;
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude);
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:centerCoordinate
radius:10 // Metres
identifier:@"testLocation"];
[self.locationManager startMonitoringForRegion:region];
No he puesto el código aquí para la región DidEnter
, etc. ya que sé que funciona cuando voy a más de 100 metros de la región monitoreada.
Aquí hay una captura de pantalla de la aplicación cuando estoy a más de 10 metros de distancia de la ubicación púrpura en el mapa, los eventos de región de salida no se disparan, sin embargo, si cambio mi ubicación a Londres, se dispara y también cuando configuro mi ubicación volviendo a donde está actualmente la ubicación azul, también se dispara.
¿Alguien sabe si hay una limitación con el radio mínimo de la región o tal vez estoy haciendo algo mal?
Gracias Aaron
Basado en la respuesta de @Nevan, que indicó algún tipo de cobertura en WWDC 2013 307 (que no abordaba esto directamente), se me ocurrió una solución razonable para obtener <10m de precisión para la llegada a un lugar, aunque tengo la sensación que implementó -(void)locationManager:didVisit:
podría hacer esto más conservador de la batería, pero proporcionaría actualizaciones menos frecuentes.
Primero, tenga algunas regiones con radio de 0..150 m, y comience a monitorear. Realmente no importa, ya que el sistema parece desencadenar estos alrededor de 150 ~ 200m:
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(location.lat, location.lng) radius:50 identifier:location.name];
[_locationManager startMonitoringForRegion:region];
Entonces, implementar
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
for (CLCircularRegion *enteredRegion in _locationManager.monitoredRegions.allObjects) {
if ([enteredRegion.identifier isEqualToString:region.identifier]) {
self.locationManager.activityType = CLActivityTypeFitness;
self.locationManager.distanceFilter = 5;
[self.locationManager startUpdatingLocation];
break;
}
}
}
El sistema comenzará a monitorear e informar a su delegado una secuencia de ubicaciones, incluso si su aplicación está suspendida (necesita UIBackgroundModes
para incluir un elemento de matriz de location
).
Para verificar si una de esas ubicaciones se encuentra dentro del centro de una de sus regiones, implemente:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *firstLocation = [locations firstObject];
CGFloat const DESIRED_RADIUS = 10.0;
CLCircularRegion *circularRegion = [[CLCircularRegion alloc] initWithCenter:firstLocation.coordinate radius:DESIRED_RADIUS identifier:@"radiusCheck"];
for (CLCircularRegion *enteredRegion in _locationManager.monitoredRegions.allObjects) {
if ([circularRegion containsCoordinate:enteredRegion.center]) {
[_locationManager stopUpdatingLocation];
NSLog(@"You are within %@ of %@, @(DESIRED_RADIUS), enteredRegion.identifier);
break;
} else if ([enteredRegion containsCoordinate:circularRegion.center]) {
NSLog(@"You are within the region, but not yet %@m from %@", @(DESIRED_RADIUS), enteredRegion.identifier);
}
}
}
También querrás implementar:
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
[_locationManager stopUpdatingLocation];
}
En los últimos días, he estado probando una función de geoperimetraje en mi dispositivo con iOS 8.1 (iPhone 5S) para una aplicación desarrollada.
La aplicación registra pocas regiones en el servicio gefence de iOS. La lógica de la aplicación necesita que cada radio de la geocerca esté entre 40 y 80 metros.
Hasta ahora, veo que en las áreas con mayor cantidad de torres de telefonía móvil y puntos de acceso Wifi, la detección de geocerca es lo suficientemente buena para ingresar a las regiones. Es decir, en áreas del centro de la ciudad, áreas comerciales, etc. ''la detección de geofores funciona bien.
Desafortunadamente, ocurre lo contrario en áreas con pocas torres celulares y redes wifi. Mi vecindario, por ejemplo, tiene aproximadamente 1000 metros de ancho y 500 de alto (1KM x 0.5KM), y no hay torres de telefonía celular en él . Se piensa en pocas torres celulares, en el perímetro que rodea el vecindario. Desafortunadamente, en el perímetro del vecindario, el servicio de geocerca no detecta nada .
No hace falta decir que estoy probando con WiFi habilitado en el dispositivo.
Cuando pruebo mi aplicación en Android: el servicio geofencing en Android 4.3, 4.4 y 5.1 funciona mucho mejor que en iOS. El servicio de geoperimetraje de Android no detecta el 100% de las transiciones de región, sin embargo, detecta el 50% -90% de las transiciones de región.
Concluyo lo siguiente: si hubiera habido más torres de telefonía móvil y puntos de acceso Wifi y si Apple hubiera mejorado el servicio de geocerca, entonces la detección en dispositivos con iOS habría sido tan buena como la de Android.
Esto es más como un comentario importante. Desde el monitoreo de la región y iBeacon
Probar el soporte de monitoreo regional de la aplicación iOS
Cuando pruebe el código de monitoreo de su región en iOS Simulator o en un dispositivo, tenga en cuenta que los eventos de la región pueden no suceder inmediatamente después de cruzar un límite de la región. Para evitar notificaciones falsas, iOS no entrega notificaciones de región hasta que se cumplan ciertas condiciones de umbral. Específicamente, la ubicación del usuario debe cruzar el límite de la región, alejarse del límite en una distancia mínima y permanecer a esa distancia mínima durante al menos 20 segundos antes de que se notifiquen las notificaciones .
Las distancias umbral específicas están determinadas por el hardware y las tecnologías de ubicación que están disponibles actualmente. Por ejemplo, si Wi-Fi está desactivado, la monitorización de la región es significativamente menos precisa . Sin embargo, para fines de prueba, puede suponer que la distancia mínima es de aproximadamente 200 metros .
Esto parece ser un error en CLLocationManager
. locationManager:didExitRegion
pruebas exhaustivas utilizando diversas configuraciones de radio de región y locationManager:didExitRegion
no se locationManager:didExitRegion
forma esperada. Esto parece ser un error bastante desagradable o el monitoreo de la región no ocurre en absoluto como sugiere la documentación. Tengo el arnés de prueba disponible para cualquiera que lo desee:
http://www.mediafire.com/download/x863zkttltyalk6/LocationTest.zip
Ejecútelo en el simulador y comience la prueba seleccionando Depurar -> Ubicación -> Unidad de Freeway en el menú del simulador de iOS. El número que ve es la distancia desde el centro de la región monitoreada. El color de fondo será verde mientras el dispositivo esté dentro de la región monitoreada y rojo cuando esté fuera de la región. El texto debajo de la distancia son registros de eventos.
Después de ejecutar la aplicación, debería ver locationManager:didExitRegion
dispara a 5319 metros de la región supervisada. La ruta recorrerá cada 37 minutos y verá que el dispositivo sale de la región siempre a 5319 metros.
He enviado un radar con Apple (17064346) . Actualizaré esta respuesta una vez que los reciba. Al menos entonces tendremos algo de entrada de la fuente canónica.
Aquí está el texto detallado enviado a Apple:
Usando una aplicación de prueba en el simulador de iOS así como en un iPhone 5S, el CLLocationManager no parece despedir las devoluciones de llamada deExitRegion de una manera esperada. Independientemente del radio de la región circular que se monitorea, la devolución de llamada no ocurrirá hasta que se alcance un umbral de alrededor de 5000 metros.
Pasos para reproducir:
1. Ejecute la aplicación adjunta
2. Inicie el seguimiento de región seleccionando Depurar -> Ubicación -> Freeway Drive en el simulador de iOS
3. Controla la aplicación. El # grande indica la distancia desde el centro de la región observada.
4. Después de aproximadamente 190 segundos y 5300 metros, laReinaRegion finalmente se disparará.
Este problema no parece estar relacionado en absoluto con el tamaño de la región. De acuerdo con los documentos de Apple , incluso las regiones pequeñas son compatibles:
En iOS 6, las regiones con un radio entre 1 y 400 metros funcionan mejor en iPhone 4S o dispositivos posteriores. (En iOS 5, las regiones con un radio entre 1 y 150 metros funcionan mejor en iPhone 4S y dispositivos posteriores). En estos dispositivos, una aplicación puede recibir la región correspondiente ingresada o la notificación de región saliente dentro de 3 a 5 minutos en promedio. si no antes
Aunque los eventos de la región no suceden instantáneamente, deberían ocurrir con bastante rapidez. De los documentos de Apple :
Los eventos de la región pueden no suceder inmediatamente después de cruzar un límite de la región. Para evitar notificaciones falsas, iOS no entrega notificaciones de región hasta que se cumplan ciertas condiciones de umbral. Específicamente, la ubicación del usuario debe cruzar el límite de la región, alejarse del límite en una distancia mínima y permanecer a esa distancia mínima durante al menos 20 segundos antes de que se notifiquen las notificaciones.
Esto no es lo que estoy viendo en el arnés de prueba. En el simulador, el dispositivo siempre estará a más de 5000 metros de la región antes de que se locationManager:didExitRegion
evento locationManager:didExitRegion
evento locationManager:didExitRegion
.
Estoy de acuerdo con Michael G. Emmons , y quiero compartir mi experiencia también:
Probé mi código con tres regiones como se muestra en la imagen a continuación:
Explicando el comportamiento:
- Mi ubicación actual es la Región-1, y empiezo a monitorear las tres regiones anteriores, y llamo a requestStateForRegion, para determinar, si hay alguna región adentro, donde estoy actualmente en pie.
- Luego recibo notificaciones de "Intro", para las dos primeras regiones (región-1 y región 2), pero solo debe detectar la región-1.
- Ahora cuando entro en la región-2, obtengo la notificación de Entrar para la región-3. pero debería recibir la notificación para la región 2 aquí.
- Ahora cuando entro en la región-1 de nuevo, obtengo el evento Exit disparado para la región-3, y esto continúa.
- pero no obtengo ningún evento de entrada / salida para las dos primeras regiones, hasta que me muevo a menos de 7 km a 10 km de las dos primeras regiones.
Comportamiento esperado: - El evento de entrada / salida debe activarse solo cuando estoy cruzando el límite de las regiones, o dentro de las regiones, no antes de 500 metros de la región.
Mi Asunción:
- Lo que noté después de todo el experimento, que cuando llamo "requestStateForRegion" para las tres regiones,
- detecta todas las regiones dentro de una región de radio 5000m, por eso detecta las dos primeras regiones al mismo tiempo (región-1 crea un círculo de 5000m de radio, y la región-2 entra en su rango, por eso también se detecta la región -2) )
- y cuando el usuario se mueve mucho más de 10 km, se invocarán sus eventos de salida y cuando el usuario regrese a estas regiones, se activará su evento de entrada. Es el mismo caso explicado por Aaron Wardle arriba.
- Region-3 se está detectando, porque, cuando el usuario ingresa en la región-1, es decir. A 8-9 km de la región-3, por lo que se activa el evento Salir, y cuando el usuario está en la ruta para la región-2, incluso cuando la región-3 está a 5000 metros, aún detecta la región-3 y dispara , Ingrese el evento para la región-3.
Por lo tanto, creo que se están detectando todas las regiones dentro de los 5000 metros y, a medida que el usuario se aleja a 10 km de la región detectada, se activará su evento de Salida. de lo contrario, si el usuario está dentro del rango de 5 km, nunca volverá a llamarlo eventos de entrada / salida.
Actualízame, si alguien ha solucionado este problema, o documentos de Apple en cualquier lugar sobre este tema.
Geofencing funciona detectando a un usuario que se mueve desde una torre de red de celda a otra torre de red de celda.
Por lo tanto, el área más pequeña que puede definir viene dictada por la proximidad de las torres de celdas.
Dentro de un centro comercial o estadio deportivo, es posible que pueda hacer 10 metros: las torres de telefonía a menudo están muy juntas. En un área regional, cualquier cosa menor de 100 km puede fallar.
Si necesita áreas más pequeñas, necesita usar bluetooth en lugar de torres de telefonía (iBeacons). Si hay un dispositivo bluetooth de baja energía en el área objetivo, puede establecer el rango en muy corto (centímetros) o razonablemente grande (hasta 30 metros o menos). Tenga en cuenta que todo esto depende de la calidad del hardware iBeacon, algunos son mejores que otros.
Lamentablemente, las únicas torres de red de celdas (versión 4.0 o más nuevas) y de celdas son la única forma de supervisar las ubicaciones sin agotar la batería de manera significativa. Mantener el GPS activo para verificar un límite de 10 metros drenaría la batería de completamente a completamente plana en aproximadamente 2 horas, incluso con la pantalla apagada.
Me gustan las respuestas de Michael y Nevan. Me gustaría agregar más información de mi experiencia / opinión personal en el desarrollo de la aplicación de iOS basada en ubicación con Region Monitoring y también destacar algunos puntos importantes:
Sea realista en el monitoreo de la región
Region Monitoring utiliza el Sistema de Posicionamiento Global (GPS), Wifi y otras tecnologías para determinar si el dispositivo está dentro o fuera de la región monitoreada. No olvide que nuestra tierra tiene 510 kilómetros cuadrados y aproximadamente el 30% son tierras (149 millones de km2). Es un área enorme ¿Recuerdas el reciente caso ausente MH370? Nuestra tecnología actual más avanzada no podía identificar una región estimada de ese avión perdido.
Si desea monitorear una región pequeña con solo 10 metros de radio . Posiblemente podría funcionar dentro de una ciudad muy densa con muchas torres de telefonía móvil y áreas conectadas a wifi. Pero al mismo tiempo, la señal podría ser bloqueada por torres de gran altura que podrían causar la pérdida de señal durante unos segundos / minutos, lo que causó la demora en la entrega de la notificación.
Entonces, realmente debe considerar la información anterior antes de decidir qué tan grande es la región que desea monitorear. Personalmente, creo que el radio de 10 metros es demasiado pequeño.
Sea realista sobre el número de regiones supervisadas
La tecnología Core Location actual solo puede monitorear hasta un máximo de 20 regiones en una sola aplicación. Asegúrese de que las regiones supervisadas no estén demasiado cerca la una de la otra también.
Personalmente he probado 3 regiones que tienen alrededor de 100 metros de radio, que se encuentran a unos 200 metros una de la otra. A veces puedo obtener notificaciones de todas estas 3 regiones cuando estoy manejando a través de ellas, pero a veces, solo puedo recibir la notificación de la Primera región solamente. ¿Cuál podría ser la razón? No podría saber Las regiones pueden estar demasiado cerca la una de la otra. O las torres de telefonía celular deciden que mi dispositivo no se encuentra dentro de la región monitoreada.
Había una persona en que desea monitorear 1800 puntos en nuestra Tierra. No seas como él, ya que es bastante poco realista y probablemente no comprenda la limitación de la tecnología Core Location
actual. Enlace : compruebe si la ubicación del usuario está cerca de algunos puntos
Ajuste fino The LocationManager
Si su aplicación necesita monitorear un área pequeña o necesita la actualización de ubicación con frecuencia. Estas son las propiedades potenciales de su administrador de ubicación.
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
kCLLocationAccuracyBestForNavigation
consumirá más batería en comparación con kCLLocationAccuracyBest
. Pero, será más preciso.
Encontré una falla en el monitoreo de la región en iOS 7 cuando hay múltiples notificaciones activadas al mismo tiempo en diferentes regiones monitoreadas. He encontrado una solución para filtrar este problema. Para obtener más información, por favor visite: Region Monitoring Glitch en iOS 7 - Múltiples notificaciones al mismo tiempo
No seas demasiado ambicioso
Es posible que haya utilizado algunas aplicaciones que pueden controlar una región pequeña y son muy precisas y pueden notificarlo en el mismo momento en que entra a la región. Y tiene la inspiración para desarrollar exactamente la misma aplicación para competir con ellos. ¿Pero entiendes lo que sucede detrás de la escena? ¿Qué tecnologías adicionales están usando? ¿Y con qué socios están colaborando?
Investigué sobre eso y descubrí que algunas de las tecnologías que usan no están disponibles públicamente. Algunas de esas compañías están fuertemente financiadas y podrían pagar una prima a las compañías de telecomunicaciones con el fin de obtener la mejor precisión de ubicación para la mejor experiencia de usuario. No entiendo los detalles sobre cómo funciona. Creo que la mayor parte de la determinación de la ubicación está en realidad en el extremo del servidor (back end), no en el móvil (front end).
Entonces, las aplicaciones desarrolladas por esas compañías no solo pueden identificar la mejor ubicación precisa, sino que además no consumen mucha batería.
NOTA : Solo quiero compartir mis 2 centavos. La información anterior consiste en mi experiencia y opinión personal. Puede que no sea 100% preciso ya que todavía estoy aprendiendo Ubicación central y Monitoreo de región .
No creo que el monitoreo de la región funcione bien para un radio tan pequeño.
- La mejor precisión con el chip GPS y
kCLLocationAccuracyBestForNavigation
menudo es de solo 10 metros. - Apple dice (en el PG de ubicación y mapas ) que se debe asumir que la distancia mínima para las regiones es de 200 metros
- Escuché que el monitoreo de la región está usando WiFi para obtener su posición (lo cual tiene sentido para el ahorro de energía). La precisión WiFi es más como 20m-100m. No estoy seguro de cómo otra aplicación usando la ubicación de fondo (es decir, usando el GPS) afectaría esto. Probablemente, el administrador de la ubicación compartiría información para mejorar la precisión.
- El monitoreo de la región puede tardar 30 segundos en dispararse una vez dentro de una región, y un par de minutos después de salir de una región (para evitar que fallas en la ubicación lo desencadenen).
- Cuando se introdujo por primera vez el monitoreo de la región, dijeron que solo funcionaría con regiones de 100 millones de habitantes y cualquier cosa más pequeña se incrementaría. Esto probablemente todavía suceda.
- Hay un método obsoleto
startMonitoringForRegion:desiredAccuracy:
que le permitió especificar la distancia más allá del borde de la región para comenzar a generar notificaciones. Es de suponer que esta característica se hastartMonitoringForRegion:
enstartMonitoringForRegion:
pero todavía está allí. Una región de 10 m podría terminar con un buffer de 10 m. - Si desea hacer esto, especifique una región más grande alrededor de donde desea monitorear, y cuando el dispositivo se active en esa región, inicie las actualizaciones de ubicación de fondo (GPS) y use
CLCircularRegion
''sCLCircularRegion
-containsCoordinate:
para activar cuando el dispositivo está dentro 10 m manualmente Este método es sancionado oficialmente por Apple (ver WWDC 2013 Session 307).
De los documentos de CLCircularRegion
:
Recuerde que el administrador de la ubicación no genera notificaciones inmediatamente después de cruzar un límite de la región. En su lugar, aplica criterios de tiempo y distancia para garantizar que el cruce esté destinado y debe desencadenar una notificación genuinamente. Así que elija un punto central y un radio que sean apropiados y que le den tiempo suficiente para alertar al usuario.
Desde la ubicación y mapas PG :
Los eventos de la región pueden no suceder inmediatamente después de cruzar un límite de la región. Para evitar notificaciones falsas, iOS no entrega notificaciones de región hasta que se cumplan ciertas condiciones de umbral. Específicamente, la ubicación del usuario debe cruzar el límite de la región, alejarse del límite en una distancia mínima y permanecer a esa distancia mínima durante al menos 20 segundos antes de que se notifiquen las notificaciones.
Las distancias umbral específicas están determinadas por el hardware y las tecnologías de ubicación que están disponibles actualmente. Por ejemplo, si Wi-Fi está desactivado, la monitorización de la región es significativamente menos precisa. Sin embargo, para fines de prueba, puede suponer que la distancia mínima es de aproximadamente 200 metros.
Kevin McMahon , quien le preguntó a los ingenieros de Core Location acerca del monitoreo de la región en un laboratorio de la WWDC de 2012, se basará en esta información. Esta información habrá cambiado mientras tanto, pero la parte sobre las categorías de la región es interesante. Aquí hay una edición:
Región fina (0 - 150 m)
- Con el piso de 100 m, el rango de esta categoría es efectivamente de 100-150 m.
- Para las regiones, este rendimiento de tamaño depende en gran medida del hardware relacionado con la ubicación
- La cantidad de tiempo que lleva Core Location para detectar y llamar al método de delegado apropiado es de aproximadamente 2-3 minutos en promedio después de que se haya cruzado el límite de la región.
- Algunos desarrolladores han descubierto independientemente que las regiones más pequeñas verían devoluciones de llamada más rápidas y agruparían regiones más pequeñas para cubrir un área grande para mejorar las notificaciones de cruce de la región.
Sounds que incluso 1 metro debería funcionar (y funcionar mejor en dispositivos iPhone 4S +):
startMonitoringForRegion:
(...)
En iOS 6, las regiones con un radio entre 1 y 400 metros funcionan mejor en iPhone 4S o dispositivos posteriores. (En iOS 5, las regiones con un radio entre 1 y 150 metros funcionan mejor en iPhone 4S y dispositivos posteriores). En estos dispositivos, una aplicación puede recibir la región correspondiente ingresada o la notificación de región saliente dentro de 3 a 5 minutos en promedio. si no antes