iOS Geofence CLCircularRegion мониторинг. locationManager:didExitRegion не работает должным образом

В настоящее время я пытаюсь настроить приложение для мониторинга определенных регионов, используя CoreLocation однако я обнаружил, что он не работает должным образом, мне кажется, что он не может работать с небольшим небольшим радиусом, установленным для каждого местоположения, т.е. 10 м.

Я также собрал небольшое тестовое приложение, которое отображает радиус круга на карте, чтобы я мог визуально видеть, что происходит.

Код, который я использую для мониторинга местоположений, выглядит следующим образом:

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];

Я не поставил здесь код для DidEnter регион и т. д., поскольку я знаю, что это работает, когда я ухожу на расстояние более 100 м от контролируемого региона.

Вот снимок экрана приложения, когда я нахожусь на расстоянии более 10 метров от пурпурного местоположения на карте, события региона выхода действительно не запускаются, однако, если я переключаю свое местоположение в Лондон, оно срабатывает, а также когда я задаю свое местоположение туда, где в данный момент находится синее местоположение, оно также срабатывает.

Пример региона

Кто-нибудь знает, есть ли ограничение с минимальным радиусом области вообще или возможно я делаю что-то не так.

Спасибо Аарон

9 ответов

Решение

Я не думаю, что мониторинг региона будет хорошо работать для такого маленького радиуса.

  • Лучшая точность с чипом GPS и kCLLocationAccuracyBestForNavigation часто всего 10 метров.
  • Apple говорит (в PG Location & Maps), что минимальное расстояние для регионов должно быть 200 м
  • Я слышал, что мониторинг региона использует WiFi, чтобы получить свою позицию (что имеет смысл для экономии энергии). Точность WiFi больше похожа на 20-100м. Я не уверен, как это повлияет на работу другого приложения, использующего фоновое местоположение (например, с помощью GPS). Возможно, менеджер местоположения поделится информацией, чтобы повысить точность.
  • Мониторинг региона может занять 30 секунд, чтобы выстрелить один раз внутри региона, и пару минут, чтобы выстрелить после того, как он покинул регион (чтобы не дать сбою местоположения вызвать его).
  • Когда впервые был введен мониторинг регионов, они сказали, что он будет работать только с 100-метровыми регионами, и что-либо меньшее будет увеличено. Это, вероятно, все еще происходит.
  • Есть устаревший метод startMonitoringForRegion:desiredAccuracy: что позволило вам указать расстояние до границы региона, чтобы начать генерировать уведомления. Предположительно эта функция была включена в startMonitoringForRegion: но все еще там. 10-метровая область может закончиться 10-миллиметровым буфером.
  • Если вы хотите сделать это, укажите большую область вокруг того места, где вы хотите отслеживать, и когда устройство проснется в этом регионе, запустите фоновые обновления местоположения (GPS) и используйте CLCircularRegion "s -containsCoordinate: для запуска, когда устройство находится в пределах 10 м вручную. Apple официально утвердила этот метод (см. Сессия 307 WWDC 2013).

От CLCircularRegion документы:

Помните, что менеджер местоположений не генерирует уведомления сразу после пересечения границы региона. Вместо этого он применяет критерии времени и расстояния, чтобы гарантировать, что пересечение было запланировано, и должно действительно вызвать уведомление. Поэтому выберите подходящую центральную точку и радиус и дайте вам достаточно времени, чтобы предупредить пользователя.

От местоположения и карт PG:

События региона могут не произойти сразу после пересечения границы региона. Чтобы предотвратить ложные уведомления, iOS не доставляет уведомления региона, пока не будут выполнены определенные пороговые условия. В частности, местоположение пользователя должно пересекать границу региона, отойти от границы на минимальное расстояние и оставаться на этом минимальном расстоянии не менее 20 секунд, прежде чем будут отправлены уведомления.
Конкретные пороговые расстояния определяются аппаратным обеспечением и технологиями определения местоположения, которые в настоящее время доступны. Например, если Wi-Fi отключен, мониторинг региона будет значительно менее точным. Однако для целей тестирования можно предположить, что минимальное расстояние составляет примерно 200 метров.

В этом посте есть еще кое-что из того, что написал Кевин МакМахон, который спросил инженеров Центрального местоположения о мониторинге региона в лаборатории на WWDC 2012. Тем временем эта информация изменится, но часть о категориях регионов интересна. Вот редактирование:

Прекрасный регион (0 - 150 м)
- При высоте пола 100 метров диапазон этой категории составляет 100-150 метров.
- Для регионов этот размер производительности сильно зависит от оборудования, связанного с местоположением
- Количество времени, которое требуется Базовому местоположению, чтобы обнаружить и вызвать соответствующий метод делегата, составляет в среднем приблизительно 2-3 минуты после того, как граница региона была пересечена.
- Некоторые разработчики независимо друг от друга выяснили, что меньшие регионы будут видеть более быстрые обратные вызовы и будут кластеризовать меньшие регионы, чтобы охватить одну большую область, чтобы улучшить уведомления о пересечении регионов.

Кажется, это ошибка в CLLocationManager, Я провел обширное тестирование с использованием различных конфигураций радиуса области и locationManager:didExitRegion не стреляет ожидаемым образом. Кажется, это либо довольно неприятная ошибка, либо мониторинг региона вообще не происходит, как предполагает документация. У меня есть тестовая проводка, доступная всем, кто хочет:

http://www.mediafire.com/download/x863zkttltyalk6/LocationTest.zip

Запустите его в симуляторе и запустите тестирование, выбрав "Отладка -> Местоположение -> Автострада" в меню симулятора iOS. Число, которое вы видите, является расстоянием от центра контролируемой области. Цвет фона будет зеленым, когда устройство находится в контролируемой области, и красным, если он находится за пределами региона. Текст под расстоянием - это журналы событий.

После запуска приложения вы должны увидеть locationManager:didExitRegion пожар в 5319 метрах от контролируемой области. Маршрут будет проходить каждые 37 минут, и вы всегда увидите, как устройство выходит из региона на расстоянии 5319 метров.

Я отправил радар с Apple (17064346). Я обновлю этот ответ, как только получу ответ. По крайней мере, тогда мы получим некоторый вклад от канонического источника.

Вот подробный текст, отправленный в Apple:

Используя тестовое приложение на симуляторе iOS, а также на iPhone 5S, CLLocationManager, похоже, не выполняет ожидаемые обратные вызовы didExitRegion. Независимо от радиуса контролируемой круговой области, обратный вызов не произойдет, пока не будет достигнут порог в 5000 метров.

Действия по воспроизведению:
1. Запустите приложенное приложение
2. Запустите отслеживание региона, выбрав "Отладка" -> "Расположение" -> "Автострада" в симуляторе iOS.
3. Контролировать приложение. Большой знак # указывает расстояние от центра наблюдаемой области.
4. Примерно через 190 секунд и 5300 метров didExitRegion, наконец, выстрелит.

Эта проблема, похоже, вообще не связана с размером региона. Согласно документации Apple, поддерживаются даже небольшие регионы:

В iOS 6 регионы с радиусом от 1 до 400 метров работают лучше на устройствах iPhone 4S или новее. (В iOS 5 регионы с радиусом от 1 до 150 метров работают лучше на устройствах iPhone 4S и более поздних версиях.) На этих устройствах приложение может ожидать получения соответствующего введенного региона или уведомления о выходе из региона в среднем в течение 3-5 минут, если не раньше.

Хотя региональные события не происходят мгновенно, они должны происходить довольно быстро. Из документов Apple:

События региона могут не произойти сразу после пересечения границы региона. Чтобы предотвратить ложные уведомления, iOS не доставляет уведомления региона, пока не будут выполнены определенные пороговые условия. В частности, местоположение пользователя должно пересекать границу региона, отойти от границы на минимальное расстояние и оставаться на этом минимальном расстоянии не менее 20 секунд, прежде чем будут отправлены уведомления.

Это совсем не то, что я вижу в тестовом жгуте. На симуляторе устройство всегда будет на расстоянии более 5000 метров от региона до locationManager:didExitRegion событие происходит.

Мне нравятся ответы как Майкла, так и Невана. Я хотел бы добавить больше информации из моего личного опыта / мнения в разработке iOS-приложения на основе местоположения с мониторингом региона, а также выделить несколько важных моментов:-

Будьте реалистами в области мониторинга региона

Мониторинг региона использует Глобальную систему позиционирования (GPS), Wi-Fi и другие технологии, чтобы определить, находится ли устройство внутри или за пределами контролируемой области. Не забывайте, что наша земля составляет 510 квадратных километров, и около 30% приходится на землю (149 миллионов км2). Это огромная территория. Помните недавний случай пропажи MH370? Наша самая современная технология не может даже определить предполагаемую область этой недостающей плоскости.

Если вы хотите контролировать небольшой регион с радиусом всего 10 метров. Это может работать в очень плотном городе с множеством вышек сотовой связи и Wi-Fi. Но в то же время сигнал может быть заблокирован высотными вышками, что может привести к потере сигнала на несколько секунд / минут, что привело к задержке доставки уведомления.

Таким образом, вы действительно должны рассмотреть вышеупомянутую информацию, прежде чем решить, насколько велик регион, который вы хотите отслеживать. Лично я считаю, что радиус 10 метров слишком мал.

Будьте реалистами в отношении количества контролируемых регионов

Текущая технология определения местоположения может контролировать только до 20 регионов в одном приложении. Убедитесь, что отслеживаемые области не слишком близко расположены друг к другу.

Я лично проверил 3 региона, радиус которых составляет около 100 метров, а расстояние до них около 200 метров. Иногда я могу получать уведомления из всех этих трех регионов, когда проезжаю через них, но иногда я могу получать уведомления только из Первого региона. Что может быть причиной? Я не мог знать. Регионы могут быть слишком близко друг к другу. Или вышки сотовой связи решают, что мое устройство на самом деле не находится в контролируемой области.

На StackOverFlow был один человек, который хочет отслеживать 1800 точек на нашей Земле. Не будь таким, как он, потому что он совершенно нереалистичен и, вероятно, не понимает ограничения тока Core Location технология. Ссылка: проверьте, находится ли местоположение пользователя рядом с некоторыми точками

Тонкая настройка LocationManager

Если вашему приложению необходимо отслеживать небольшую область или часто обновлять местоположение. Вот потенциальные свойства вашего менеджера местоположения.

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;

kCLLocationAccuracyBestForNavigation будет потреблять больше батареи по сравнению с kCLLocationAccuracyBest, Но это будет точнее.

Я обнаружил сбой в мониторинге области в iOS 7, когда в разных отслеживаемых регионах одновременно запускается несколько уведомлений. Я нашел решение, чтобы отфильтровать этот глюк. Для получения дополнительной информации, пожалуйста, посетите: Регион мониторинга сбоев на iOS 7 - несколько уведомлений одновременно

Не будь слишком амбициозным

Возможно, вы использовали некоторые приложения, которые могут отслеживать небольшой регион, они очень точны и способны уведомить вас в ту же секунду, когда вы входите в регион. И у вас есть вдохновение для разработки точно такого же приложения, чтобы конкурировать с ними. Но вы понимаете, что происходит за сценой? Какие дополнительные технологии они используют? И с какими партнерами они сотрудничают?

Я провел некоторое исследование по этому вопросу и обнаружил, что некоторые из технологий, которые они используют, не доступны публично. Некоторые из этих компаний получают значительные средства и могут платить телекоммуникационным компаниям премию, чтобы получить максимальную точность определения местоположения для лучшего взаимодействия с пользователем. Я не понимаю деталей о том, как это работает. Я считаю, что большая часть определения местоположения на самом деле на стороне сервера (бэкэнд), а не на мобильном (интерфейс).

Таким образом, приложения, разработанные этими компаниями, могут не только определить точное местоположение, но и не потребляют много энергии.

ПРИМЕЧАНИЕ: я просто хочу поделиться своими 2 центами. Приведенная выше информация состоит из моего опыта и личного мнения. Это может быть не на 100% точно, так как я все еще изучаю базовое местоположение и мониторинг региона.

Я согласен с Майклом Дж. Эммонсом и хочу поделиться своим опытом:

Я проверил свой код с тремя областями, как показано на рисунке ниже:

введите описание изображения здесь

Объясняя поведение:

  • Мое текущее местоположение - Регион-1, и я начинаю мониторинг для вышеупомянутых трех областей и вызываю requestStateForRegion, чтобы определить, есть ли внутри какой-либо регион, где я сейчас нахожусь.
  • Затем я получаю уведомления "Ввод" для первых двух регионов (регион-1 и регион 2), но он должен обнаруживать только регион-1.
  • Теперь, когда я вхожу в регион-2, я получаю уведомление Enter для региона-3. но я должен получить уведомление для региона-2 здесь.
  • Теперь, когда я снова вхожу в регион-1, я получаю событие Exit для региона-3, и это продолжается.
  • но я не получаю никаких событий входа / выхода для первых двух регионов, пока не перейду не менее чем на 7-10 км от первых двух регионов.

Ожидаемое поведение: - Событие входа / выхода должно вызываться только тогда, когда я пересекаю границу регионов или внутри регионов, не ранее, чем в 500 метрах от региона.

Мое предположение:

  • После всего эксперимента я заметил, что когда я вызываю "requestStateForRegion" для всех трех регионов,
  • он обнаруживает все области внутри области радиусом 5000 м, поэтому он обнаруживает первые две области одновременно (область-1 создает круг радиусом 5000 м, а область-2 попадает в его диапазон, поэтому область -2 также обнаруживается).
  • и когда пользователь перемещается намного больше, чем на 10 км, будут вызваны его события выхода, а когда пользователь вернется в эти регионы, его событие ввода будет запущено. Это тот же случай, который объяснил Аарон Уордл выше.
  • Регион-3 обнаруживается, потому что, когда пользователь входит в регион-1, т.е. 8-9 км от региона-3, поэтому для этого запускается событие Exit, и когда пользователь находится на маршруте для региона-2, здесь, даже если регион-3 находится на расстоянии 5000 метров, он все равно обнаруживает регион-3 и срабатывает, Введите событие для региона-3.

Поэтому я думаю, что все области внутри 5000 метров обнаруживаются, и когда пользователь уходит в 10 км от обнаруженной области, его событие Exit будет запущено. в противном случае, если пользователь находится в диапазоне 5 км, он никогда больше не будет вызывать события Enter/Exit.

Пожалуйста, сообщите мне, если кто-то исправил эту проблему, или Apple документирует где-либо эту проблему.

Основываясь на ответе @ Невана, который указывал на своего рода освещение в WWDC 2013 307 (в котором это непосредственно не рассматривается), я нашел разумное решение для получения точности < 10 м для прибытия в какое-либо место, хотя у меня есть чувство что реализация -(void)locationManager:didVisit: может сделать это более консервативным, но будет предоставлять менее частые обновления.

Во-первых, есть несколько регионов с радиусом 0..150 м и начните мониторинг. На самом деле это не имеет значения, так как система запускает их на расстоянии 150-200 м:

_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];

Затем реализовать

-(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;
        }
    }
}

Система начнет отслеживать и сообщать вашему делегату поток местоположений, даже если ваше приложение приостановлено (необходимо UIBackgroundModes включать location элемент массива).

Чтобы проверить, находится ли одно из этих мест в центре одного из ваших регионов, выполните:

-(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);
        }
    }
}

Вы также захотите реализовать:

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    [_locationManager stopUpdatingLocation];
}

Это больше похоже на важный комментарий. Из регионального мониторинга и iBeacon

Тестирование поддержки мониторинга приложений в iOS

При тестировании кода мониторинга вашего региона в iOS Simulator или на устройстве следует понимать, что события региона могут происходить не сразу после пересечения границы региона. Чтобы предотвратить ложные уведомления, iOS не доставляет уведомления региона, пока не будут выполнены определенные пороговые условия. В частности, местоположение пользователя должно пересекать границу региона, отойти от границы на минимальное расстояние и оставаться на этом минимальном расстоянии не менее 20 секунд, прежде чем будут отправлены уведомления.

Конкретные пороговые расстояния определяются аппаратным обеспечением и технологиями определения местоположения, которые в настоящее время доступны. Например, если Wi-Fi отключен, мониторинг региона будет значительно менее точным. Однако для целей тестирования можно предположить, что минимальное расстояние составляет примерно 200 метров.

Похоже, что даже 1 метр должен работать (и работать лучше на устройствах iPhone 4S+):

startMonitoringForRegion:

(...)

В iOS 6 регионы с радиусом от 1 до 400 метров работают лучше на устройствах iPhone 4S или новее. (В iOS 5 регионы с радиусом от 1 до 150 метров работают лучше на устройствах iPhone 4S и более поздних версиях.) На этих устройствах приложение может ожидать получения соответствующего введенного региона или уведомления о выходе из региона в среднем в течение 3-5 минут, если не раньше.

В последние несколько дней я тестировал функцию геозонирования на моем устройстве iOS 8.1 (iPhone 5S) для приложения, разработанного iv'e.
Приложение регистрирует несколько регионов в сервисе iOS Gefence. Логика приложения требует, чтобы каждый радиус геозоны составлял от 40 до 80 метров.
Пока я вижу, что в областях с большим количеством вышек сотовой связи и горячих точек Wi-Fi, обнаружение геозоны достаточно хорошо при входе в регионы. То есть в центральных районах города, деловых районах и т. Д. Обнаружение геозоны работает нормально.

К сожалению, в районах, где мало сотовых вышек и сетей Wi-Fi, происходит обратное. Мой район, например, имеет ширину около 1000 метров и высоту 500 метров (1 км х 0,5 км), и в нем нет сотовых вышек. По периметру, который окружает окрестности, есть несколько вышек сотовой связи. К сожалению, по периметру квартала служба геозоны ничего не обнаруживает.

Само собой разумеется, что я тестирую с включенным Wi-Fi на устройстве.

Когда я тестирую свое приложение на Android: сервис геозон для Android 4.3, 4.4 и 5.1 работает намного лучше, чем на iOS. Служба геоизображения Android не обнаруживает 100% переходов по регионам, однако обнаруживает 50%-90% переходов по регионам.

Я заключаю следующее: если бы было больше сотовых вышек и горячих точек Wi-Fi, и если бы Apple улучшила службу геозоны, обнаружение на устройствах iOS было бы таким же хорошим, как в Android.

Геозонирование работает путем обнаружения перемещения пользователя от одной вышки сотовой сети к другой вышке сотовой сети.

Поэтому наименьшая область, которую вы можете определить, определяется тем, насколько близко расположены вышки сотовой связи.

Внутри торгового центра или спортивного стадиона это может быть в состоянии сделать 10 метров - вышки сотовой связи часто очень близко друг к другу. В региональном районе все, что меньше 100 км, может потерпеть неудачу.

Если вам нужны меньшие площади, вам нужно использовать Bluetooth вместо вышек сотовой связи (iBeacons). Если в целевой области есть устройство Bluetooth с низким энергопотреблением, вы можете установить диапазон очень короткий (сантиметры) или достаточно большой (до 30 метров или около того). Обратите внимание, что все зависит от качества оборудования iBeacon, некоторые из них лучше, чем другие.

К сожалению, блютуз (версия 4.0 или новее) и вышки сотовой сети являются единственным способом мониторинга местоположений без существенного разряда батареи. Поддержание GPS в активном состоянии для проверки 10-метровой границы разряжает батарею от полной до полной разрядки примерно через 2 часа даже при выключенном экране.

Другие вопросы по тегам