Вы можете использовать функцию определения местоположения Wi-Fi, предоставляемую API Wi-Fi RTT (Round-Trip-Time), для измерения расстояния до ближайших точек доступа Wi-Fi с поддержкой RTT и других устройств, поддерживающих Wi-Fi .
Если измерить расстояние до трех или более точек доступа, можно использовать алгоритм многосторонней локализации для оценки положения устройства, которое наилучшим образом соответствует этим измерениям. Результат обычно имеет точность в пределах 1-2 метров.
Благодаря такой точности можно разрабатывать высокоточные сервисы на основе местоположения, такие как навигация внутри помещений, голосовое управление с возможностью уточнения параметров (например, «Включите этот свет») и предоставление информации на основе местоположения (например, «Есть ли специальные предложения на этот товар?»).
Для измерения расстояния с помощью Wi-Fi RTT запрашивающему устройству не нужно подключаться к точкам доступа. Для обеспечения конфиденциальности только запрашивающее устройство может определить расстояние до точки доступа; точки доступа не обладают этой информацией. Для приложений, работающих в фоновом режиме, использование Wi-Fi RTT не ограничено, но для приложений, работающих в фоновом режиме, скорость передачи данных снижается.
Технология Wi-Fi RTT и связанные с ней возможности точного измерения времени (FTM) определены стандартом IEEE 802.11-2016. Wi-Fi RTT требует точного измерения времени, обеспечиваемого FTM, поскольку вычисляет расстояние между двумя устройствами, измеряя время, необходимое пакету для совершения кругового пути между устройствами, и умножая это время на скорость света.
В Android 15 (уровень API 35) была добавлена поддержка определения расстояния без триггера (NTB) по стандарту IEEE 802.11az.
Различия в реализации в зависимости от версии Android.
Протокол Wi-Fi RTT был представлен в Android 9 (уровень API 28). При использовании этого протокола для определения местоположения устройства с помощью многосторонней латерализации на устройствах под управлением Android 9 вам необходим доступ к предварительно заданным данным о местоположении точек доступа (AP) в вашем приложении. Вы сами решаете, как хранить и получать эти данные.
На устройствах под управлением Android 10 (уровень API 29) и выше данные о местоположении точки доступа могут быть представлены в виде объектов ResponderLocation , которые включают широту, долготу и высоту. Для точек доступа Wi-Fi RTT, поддерживающих информацию о конфигурации местоположения/отчет о местоположении (данные LCI/LCR), протокол вернет объект ResponderLocation в процессе определения расстояния .
Эта функция позволяет приложениям напрямую запрашивать у точек доступа их местоположение, вместо того чтобы хранить эту информацию заранее. Таким образом, ваше приложение может находить точки доступа и определять их местоположение, даже если они ранее не были известны, например, когда пользователь входит в новое здание.
Поддержка измерения расстояния по стандарту IEEE 802.11az NTB доступна на устройствах под управлением Android 15 (уровень API 35) и выше. Это означает, что если устройство поддерживает режим инициатора IEEE 802.11az NTB (обозначается параметром WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR ), ваше приложение сможет найти точки доступа, поддерживающие как IEEE 802.11mc, так и IEEE 802.11az, с помощью одного запроса на измерение расстояния. API RangingResult был расширен для предоставления информации о минимальном и максимальном значении, которое можно использовать для интервала между измерениями расстояния, оставляя точный интервал под контролем вашего приложения.
Требования
- Аппаратное обеспечение устройства, отправляющего запрос на определение расстояния, должно реализовывать стандарт 802.11-2016 FTM или стандарт 802.11az (определение расстояния без триггера).
- Устройство, отправляющее запрос на определение расстояния, должно работать под управлением Android 9 (уровень API 28) или более поздней версии. Определение расстояния без триггера по стандарту IEEE 802.11az включено на устройствах под управлением Android 15 (уровень API 35) и выше.
- На устройстве, отправляющем запрос на определение местоположения, должны быть включены службы определения местоположения и включено сканирование Wi-Fi (в разделе «Настройки» > «Местоположение» ).
- Если приложение, отправляющее запрос на определение местоположения, ориентировано на Android 13 (уровень API 33) или выше, оно должно иметь разрешение
NEARBY_WIFI_DEVICES. Если такое приложение ориентировано на более раннюю версию Android, оно должно иметь разрешениеACCESS_FINE_LOCATION. - Приложение должно запрашивать информацию о диапазоне точек доступа, пока оно находится в видимом режиме или работает в фоновом режиме. Приложение не может получать доступ к информации о местоположении из фонового режима .
- Точка доступа должна поддерживать стандарт IEEE 802.11-2016 FTM или стандарт IEEE 802.11az (определение расстояния без триггера).
Настраивать
Чтобы настроить приложение для использования Wi-Fi RTT, выполните следующие шаги.
1. Запросить разрешения
В манифесте вашего приложения запросите следующие разрешения:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- If your app targets Android 13 (API level 33)
or higher, you must declare the NEARBY_WIFI_DEVICES permission. -->
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
<!-- If your app derives location information from Wi-Fi APIs,
don't include the "usesPermissionFlags" attribute. -->
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
<!-- If any feature in your app relies on precise location
information, don't include the "maxSdkVersion"
attribute. -->
android:maxSdkVersion="32" />
Разрешения NEARBY_WIFI_DEVICES и ACCESS_FINE_LOCATION являются опасными, поэтому их необходимо запрашивать во время выполнения каждый раз, когда пользователь хочет выполнить сканирование RTT. Вашему приложению потребуется запросить разрешение пользователя, если оно еще не было предоставлено. Для получения дополнительной информации о разрешениях во время выполнения см. раздел «Запрос разрешений приложения» .
2. Проверьте, поддерживает ли устройство Wi-Fi RTT.
Чтобы проверить, поддерживает ли устройство Wi-Fi RTT, используйте API PackageManager :
Котлин
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
3. Проверьте наличие Wi-Fi RTT.
Функция Wi-Fi RTT может быть установлена на устройстве, но она может быть недоступна, поскольку пользователь отключил Wi-Fi. В зависимости от возможностей аппаратного и программного обеспечения, некоторые устройства могут не поддерживать Wi-Fi RTT, если используется SoftAP или режим модема. Чтобы проверить доступность Wi-Fi RTT, вызовите функцию isAvailable() .
Доступность Wi-Fi RTT может измениться в любой момент. Вашему приложению следует зарегистрировать BroadcastReceiver для получения сообщения ACTION_WIFI_RTT_STATE_CHANGED , которое отправляется при изменении доступности. Получив широковещательное сообщение, приложение должно проверить текущее состояние доступности и соответствующим образом скорректировать свое поведение.
Например:
Котлин
val filter = IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED) val myReceiver = object: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (wifiRttManager.isAvailable) { … } else { … } } } context.registerReceiver(myReceiver, filter)
Java
IntentFilter filter = new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED); BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (wifiRttManager.isAvailable()) { … } else { … } } }; context.registerReceiver(myReceiver, filter);
Для получения более подробной информации см. раздел «Трансляции» .
Создайте запрос на определение диапазона.
Запрос на определение расстояния ( RangingRequest ) создается путем указания списка точек доступа или Wi-Fi-совместимых устройств, для которых запрашивается расстояние. В одном запросе на определение расстояния можно указать несколько точек доступа или Wi-Fi-совместимых устройств; измеряются и возвращаются расстояния до всех устройств.
Например, в запросе можно использовать метод addAccessPoint() для указания точки доступа, до которой нужно измерить расстояние:
Котлин
val req: RangingRequest = RangingRequest.Builder().run { addAccessPoint(ap1ScanResult) addAccessPoint(ap2ScanResult) build() }
Java
RangingRequest.Builder builder = new RangingRequest.Builder(); builder.addAccessPoint(ap1ScanResult); builder.addAccessPoint(ap2ScanResult); RangingRequest req = builder.build();
Точка доступа идентифицируется объектом ScanResult , который можно получить, вызвав метод WifiManager.getScanResults() . Для добавления нескольких точек доступа одновременно можно использовать addAccessPoints(List<ScanResult>) .
Объекты ScanResult могут содержать точки доступа, поддерживающие как IEEE 802.11mc ( is80211mcResponder() ), так и IEEE 802.11az с определением расстояния без триггера ( is80211azNtbResponder() ). Устройства, поддерживающие определение расстояния по протоколу IEEE 802.11az NTB, выполняют определение расстояния либо по протоколу 802.11mc, либо по протоколу 802.11az в зависимости от возможностей точки доступа, по умолчанию используя протокол 802.11az, если точка доступа поддерживает оба протокола. Устройства, не поддерживающие IEEE 802.11az, выполняют все измерения расстояния с использованием протокола IEEE 802.11mc.
Аналогичным образом, запрос на определение расстояния может добавить Wi-Fi-совместимый узел, используя либо его MAC-адрес, либо PeerHandle , с помощью методов addWifiAwarePeer(MacAddress peer) и addWifiAwarePeer(PeerHandle peer) соответственно. Для получения дополнительной информации об обнаружении Wi-Fi-совместимых узлов см. документацию Wi-Fi Aware .
Запросы варьируются в зависимости от региона.
Приложение отправляет запрос на определение расстояния с помощью метода WifiRttManager.startRanging() и предоставляет следующие данные: объект RangingRequest для указания операции, объект Executor для указания контекста обратного вызова и объект RangingResultCallback для получения результатов.
Например:
Котлин
val mgr = context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE) as WifiRttManager val request: RangingRequest = myRequest mgr.startRanging(request, executor, object : RangingResultCallback() { override fun onRangingResults(results: List<RangingResult>) { … } override fun onRangingFailure(code: Int) { … } })
Java
WifiRttManager mgr = (WifiRttManager) Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE); RangingRequest request ...; mgr.startRanging(request, executor, new RangingResultCallback() { @Override public void onRangingFailure(int code) { … } @Override public void onRangingResults(List<RangingResult> results) { … } });
Операция измерения расстояния выполняется асинхронно, а результаты измерения возвращаются в одном из коллбэков класса RangingResultCallback :
- Если вся операция измерения расстояния завершается неудачей, запускается функция обратного вызова
onRangingFailureс кодом состояния, описанным вRangingResultCallback. Такая ошибка может произойти, если служба не может выполнить операцию измерения расстояния в данный момент — например, из-за отключения Wi-Fi, из-за того, что приложение запросило слишком много операций измерения расстояния и его скорость ограничена, или из-за проблем с правами доступа. - После завершения операции измерения расстояния срабатывает функция обратного вызова
onRangingResults, которая выдает список результатов, соответствующих списку запросов — по одному результату на каждый запрос. Порядок результатов не обязательно совпадает с порядком запросов. Обратите внимание, что операция измерения расстояния может завершиться успешно, но каждый результат может указывать на ошибку конкретного измерения.
Интерпретация результатов измерения расстояния
Каждый из результатов, возвращаемых функцией обратного вызова onRangingResults , определяется объектом RangingResult . При каждом запросе выполняйте следующие действия.
1. Определите запрос.
Идентифицируйте запрос на основе информации, предоставленной при создании объекта RangingRequest : чаще всего это MAC-адрес, указанный в объекте ScanResult идентифицирующий точку доступа. MAC-адрес можно получить из результатов измерения расстояния с помощью метода getMacAddress() .
Список результатов измерения расстояния может располагаться в другом порядке, чем указанные в запросе точки доступа (пиры), поэтому для идентификации пира следует использовать MAC-адрес, а не порядок результатов.
2. Определите, было ли каждое измерение успешным.
Чтобы определить, было ли измерение успешным, используйте метод getStatus() . Любое значение, отличное от STATUS_SUCCESS указывает на неудачу. Неудача означает, что все остальные поля этого результата (кроме идентификатора запроса выше) недействительны, и соответствующий метод get* завершится с исключением IllegalStateException .
3. Получите результаты для каждого успешного измерения.
Для каждого успешного измерения ( RangingResult ) вы можете получить значения результата с помощью соответствующих методов get :
Расстояние в мм и стандартное отклонение измерения:
Уровень сигнала RSSI пакетов, использованных для измерений:
Время в миллисекундах, в которое было произведено измерение (указывает время с момента загрузки):
Количество предпринятых измерений и количество успешных измерений (на основе которых производятся измерения расстояний):
Минимальное и максимальное время ожидания клиентского устройства между измерениями NTB в точке 11az:
getMinTimeBetweenNtbMeasurementsMicros()иgetMaxTimeBetweenNtbMeasurementsMicros()возвращают минимальное и максимальное время. Если запрос на следующее измерение расстояния поступает до истечения минимального времени, API возвращает кэшированный результат измерения. Если запрос на следующее измерение расстояния поступает после истечения максимального времени, API завершает сеанс измерения расстояния без триггера и согласовывает новый сеанс измерения с отвечающей станцией. Следует избегать запроса нового сеанса измерения расстояния, поскольку это увеличивает время измерения. Чтобы в полной мере использовать преимущества эффективности измерения расстояния без триггера в стандарте 802.11az, инициируйте следующий запрос на измерение расстояния между минимальным и максимальным временем измерения, указанным в предыдущем измеренииRangingResult.Количество повторений в длительном тренировочном поле (LTF), использованных станциями-ответчиками и инициаторами в преамбуле для результата NTB стандарта IEEE 802.11az:
Количество пространственно-временных потоков (STS), переданных и принятых станцией-инициатором для получения результата NTB по стандарту IEEE 802.11az:
Устройства Android, поддерживающие WiFi-RTT
В приведенных ниже таблицах перечислены некоторые телефоны , точки доступа , а также устройства для розничной торговли, складов и распределительных центров , поддерживающие WiFi-RTT. Этот список далеко не полный. Мы рекомендуем вам связаться с нами , чтобы добавить сюда список ваших продуктов, поддерживающих RTT.
Точки доступа
| Производитель и модель | Дата поддержки | Протокол |
|---|---|---|
| Nest Wifi Pro (Wi-Fi 6E) | Поддерживается | мс |
| Compulab WILD AP | Поддерживается | мс |
| Google Wi-Fi | Поддерживается | мс |
| Wi-Fi роутер Google Nest | Поддерживается | мс |
| Точка доступа Wi-Fi Google Nest | Поддерживается | мс |
| Аруба AP-635 | Поддерживается | мс |
| Cisco 9130 | Поддерживается | мс |
| Cisco 9136 | Поддерживается | мс |
| Cisco 9166 | Поддерживается | мс |
| Cisco 9164 | Поддерживается | мс |
| Cisco CW9172I | Поддерживается | мк/аз |
| Cisco CW9172H | Поддерживается | мк/аз |
| Cisco CW9176I | Поддерживается | мк/аз |
| Cisco CW9178I | Поддерживается | мк/аз |
| Аруба AP-505 | Поддерживается | мс |
| Аруба AP-515 | Поддерживается | мс |
| Аруба AP-575 | Поддерживается | мс |
| Аруба AP-518 | Поддерживается | мс |
| Аруба AP-505H | Поддерживается | мс |
| Аруба AP-565 | Поддерживается | мс |
| Аруба AP-535 | Поддерживается | мс |
| Аруба AP567 | Поддерживается | мс |
| Аруба AP577 | Поддерживается | мс |
| Аруба AP555 | Поддерживается | мс |
| Аруба AP635 | Поддерживается | мс |
| Аруба AP655 | Поддерживается | мс |
| Аруба AP615 | Поддерживается | мс |
| Аруба AP734 | Поддерживается | мк/аз |
| Аруба AP735 | Поддерживается | мк/аз |
| Аруба AP754 | Поддерживается | мк/аз |
| Аруба AP755 | Поддерживается | мк/аз |
Телефоны
| Производитель и модель | версия для Android |
|---|---|
| Google Pixel 9 Pro XL | 14+ |
| Google Pixel 9 | 14+ |
| Google Pixel 9 Pro | 14+ |
| Google Pixel 9 Pro XL | 14+ |
| Google Pixel 7a | 14+ |
| Google Pixel 7 | 14+ |
| Google Pixel 8 | 14+ |
| Google Pixel 8 Pro | 14+ |
| Google Pixel 8a | 14+ |
| Samsung SM-S918B | 14+ |
| Samsung SM-A515F | 14+ |
| Google Pixel 9 Pro | 14+ |
| Samsung SM-A546E | 14+ |
| Samsung SM-S928B | 14+ |
| Samsung SM-A217F | 14+ |
| Samsung SM-A715F | 14+ |
| Samsung SM-A528B | 14+ |
| Samsung SM-A135F | 14+ |
| Samsung SM-S911B | 14+ |
| Xiaomi 21091116AI | 14+ |
| Google Pixel 9 | 14+ |
| Samsung SM-A127F | 14+ |
| Google Pixel 7 Pro | 14+ |
| Samsung SM-A556E | 14+ |
| Пиксель 6 | 9.0+ |
| Pixel 6 Pro | 9.0+ |
| Пиксель 5 | 9.0+ |
| Пиксель 5а | 9.0+ |
| Pixel 5a 5G | 9.0+ |
| Xiaomi Mi 10 Pro | 9.0+ |
| Xiaomi Mi 10 | 9.0+ |
| Xiaomi Redmi Mi 9T Pro | 9.0+ |
| Xiaomi Mi 9T | 9.0+ |
| Xiaomi Mi 9 | 9.0+ |
| Xiaomi Mi Note 10 | 9.0+ |
| Xiaomi Mi Note 10 Lite | 9.0+ |
| Xiaomi Redmi Note 9S | 9.0+ |
| Xiaomi Redmi Note 9 Pro | 9.0+ |
| Xiaomi Redmi Note 8T | 9.0+ |
| Xiaomi Redmi Note 8 | 9.0+ |
| Xiaomi Redmi K30 Pro | 9.0+ |
| Xiaomi Redmi K20 Pro | 9.0+ |
| Xiaomi Redmi K20 | 9.0+ |
| Xiaomi Redmi Note 5 Pro | 9.0+ |
| Xiaomi Mi CC9 Pro | 9.0+ |
| LG G8X Тонкий | 9.0+ |
| LG V50S Тонкий | 9.0+ |
| LG V60 Тонкий | 9.0+ |
| LG V30 | 9.0+ |
| Samsung Galaxy Note 10+ 5G | 9.0+ |
| Samsung Galaxy S20+ 5G | 9.0+ |
| Samsung Galaxy S20+ | 9.0+ |
| Samsung Galaxy S20 5G | 9.0+ |
| Samsung Galaxy S20 Ultra 5G | 9.0+ |
| Samsung Galaxy S20 | 9.0+ |
| Samsung Galaxy Note 10+ | 9.0+ |
| Samsung Galaxy Note 10 5G | 9.0+ |
| Samsung Galaxy Note 10 | 9.0+ |
| Samsung A9 Pro | 9.0+ |
| Google Pixel 4 XL | 9.0+ |
| Google Pixel 4 | 9.0+ |
| Google Pixel 4a | 9.0+ |
| Google Pixel 3 XL | 9.0+ |
| Google Pixel 3 | 9.0+ |
| Google Pixel 3a XL | 9.0+ |
| Google Pixel 3a | 9.0+ |
| Google Pixel 2 XL | 9.0+ |
| Google Pixel 2 | 9.0+ |
| Google Pixel 1 XL | 9.0+ |
| Google Pixel 1 | 9.0+ |
| Poco X2 | 9.0+ |
| Sharp Aquos R3 SH-04L | 9.0+ |
Устройства для розничной торговли, складирования и распределительных центров.
| Производитель и модель | версия для Android |
|---|---|
| Zebra PS20 | 10.0+ |
| Zebra TC52/TC52HC | 10.0+ |
| Зебра TC57 | 10.0+ |
| Зебра TC72 | 10.0+ |
| Зебра TC77 | 10.0+ |
| Зебра MC93 | 10.0+ |
| Zebra TC8300 | 10.0+ |
| Zebra VC8300 | 10.0+ |
| Зебра EC30 | 10.0+ |
| Зебра ET51 | 10.0+ |
| Зебра ET56 | 10.0+ |
| Зебра Л10 | 10.0+ |
| Zebra CC600/CC6000 | 10.0+ |
| Zebra MC3300x | 10.0+ |
| Zebra MC330x | 10.0+ |
| Zebra TC52x | 10.0+ |
| Zebra TC57x | 10.0+ |
| Zebra EC50 (LAN и HC) | 10.0+ |
| Zebra EC55 (WAN) | 10.0+ |
| Zebra WT6300 | 10.0+ |
| Скорпио X5 | 10.0+ |