Вы можете использовать функцию определения местоположения по Wi-Fi, предоставляемую API Wi-Fi RTT (Round-Trip-Time), для измерения расстояния до ближайших точек доступа Wi-Fi с поддержкой RTT и одноранговых устройств Wi-Fi Aware .
Если вы измеряете расстояние до трёх или более точек доступа, вы можете использовать алгоритм мультилатерации для оценки положения устройства, которое наилучшим образом соответствует этим измерениям. Точность результата обычно составляет 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, поддерживающих информацию о конфигурации местоположения/отчёт о местоположении Civic (данные 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)
Ява
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)
Ява
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 Aware, для которых запрашивается диапазон. В одном запросе можно указать несколько точек доступа или пиров Wi-Fi Aware; расстояния до всех устройств измеряются и возвращаются.
Например, запрос может использовать метод addAccessPoint()
для указания точки доступа, до которой необходимо измерить расстояние:
Котлин
val req: RangingRequest = RangingRequest.Builder().run { addAccessPoint(ap1ScanResult) addAccessPoint(ap2ScanResult) build() }
Ява
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 Aware, используя либо его MAC-адрес, либо его PeerHandle
, используя методы addWifiAwarePeer(MacAddress peer)
и addWifiAwarePeer(PeerHandle peer)
соответственно. Подробнее об обнаружении пиров Wi-Fi Aware см. в документации по 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) { … } })
Ява
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), которые станции-ответчики и инициаторы использовали в преамбуле для IEEE 802.11az NTB, приводят к следующему:
Количество переданных и принятых пространственно-временных потоков (STS), которые станция-инициатор использовала для результата IEEE 802.11az NTB:
Устройства Android с поддержкой WiFi-RTT
В таблицах ниже перечислены некоторые телефоны , точки доступа , а также устройства для розничной торговли, складов и распределительных центров , поддерживающие Wi-Fi-RTT. Это далеко не полный список. Мы рекомендуем вам обратиться к нам , чтобы мы могли разместить здесь список ваших устройств с поддержкой RTT.
Точки доступа
Производитель и модель | Дата поддержки | Протокол |
---|---|---|
Nest Wifi Pro (Wi-Fi 6E) | Поддерживается | MC |
Compulab WILD AP | Поддерживается | MC |
Google Wi-Fi | Поддерживается | MC |
Wi-Fi-роутер Google Nest | Поддерживается | MC |
Точка Wi-Fi Google Nest | Поддерживается | MC |
Аруба AP-635 | Поддерживается | MC |
Cisco 9130 | Поддерживается | MC |
Cisco 9136 | Поддерживается | MC |
Cisco 9166 | Поддерживается | MC |
Cisco 9164 | Поддерживается | MC |
Cisco CW9172I | Поддерживается | мк/аз |
Cisco CW9172H | Поддерживается | мк/аз |
Cisco CW9176I | Поддерживается | мк/аз |
Cisco CW9178I | Поддерживается | мк/аз |
Аруба AP-505 | Поддерживается | MC |
Аруба AP-515 | Поддерживается | MC |
Аруба AP-575 | Поддерживается | MC |
Аруба AP-518 | Поддерживается | MC |
Аруба AP-505H | Поддерживается | MC |
Аруба AP-565 | Поддерживается | MC |
Аруба AP-535 | Поддерживается | MC |
Аруба AP567 | Поддерживается | MC |
Аруба AP577 | Поддерживается | MC |
Аруба AP555 | Поддерживается | MC |
Аруба AP635 | Поддерживается | MC |
Аруба AP655 | Поддерживается | MC |
Аруба AP615 | Поддерживается | MC |
Аруба AP734 | Поддерживается | мк/аз |
Аруба AP735 | Поддерживается | мк/аз |
Аруба AP754 | Поддерживается | мк/аз |
Аруба AP755 | Поддерживается | мк/аз |
Телефоны
Производитель и модель | Android-версия |
---|---|
Google Pixel 9 Pro XL | 14+ |
Google Пиксель 9 | 14+ |
Google Pixel 9 Pro | 14+ |
Google Pixel 9 Pro XL | 14+ |
Google Пиксель 7a | 14+ |
Google Пиксель 7 | 14+ |
Google Пиксель 8 | 14+ |
Google Pixel 8 Pro | 14+ |
Google Пиксель 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 Пиксель 9 | 14+ |
Samsung SM-A127F | 14+ |
Google Pixel 7 Pro | 14+ |
Samsung SM-A556E | 14+ |
Пиксель 6 | 9.0+ |
Пиксель 6 Про | 9.0+ |
Пиксель 5 | 9.0+ |
Пиксель 5а | 9.0+ |
Пиксель 5a 5G | 9.0+ |
Xiaomi Mi 10 Pro | 9.0+ |
Сяоми Ми 10 | 9.0+ |
Xiaomi Redmi Mi 9T Pro | 9.0+ |
Xiaomi Mi 9T | 9.0+ |
Сяоми Ми 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 ThinQ | 9.0+ |
LG V50S ThinQ | 9.0+ |
LG V60 ThinQ | 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 Пиксель 4 | 9.0+ |
Google Пиксель 4a | 9.0+ |
Google Pixel 3 XL | 9.0+ |
Google Пиксель 3 | 9.0+ |
Google Pixel 3a XL | 9.0+ |
Google Пиксель 3a | 9.0+ |
Google Pixel 2 XL | 9.0+ |
Google Пиксель 2 | 9.0+ |
Google Pixel 1 XL | 9.0+ |
Google Пиксель 1 | 9.0+ |
Poco X2 | 9.0+ |
Sharp Aquos R3 SH-04L | 9.0+ |
Устройства для розничной торговли, складирования и распределительных центров
Производитель и модель | Android-версия |
---|---|
Зебра PS20 | 10.0+ |
Зебра TC52/TC52HC | 10.0+ |
Зебра TC57 | 10.0+ |
Зебра TC72 | 10.0+ |
Зебра TC77 | 10.0+ |
Зебра MC93 | 10.0+ |
Зебра TC8300 | 10.0+ |
Зебра VC8300 | 10.0+ |
Зебра EC30 | 10.0+ |
Зебра ET51 | 10.0+ |
Зебра ET56 | 10.0+ |
Зебра Л10 | 10.0+ |
Зебра CC600/CC6000 | 10.0+ |
Зебра MC3300x | 10.0+ |
Зебра MC330x | 10.0+ |
Зебра TC52x | 10.0+ |
Зебра TC57x | 10.0+ |
Zebra EC50 (LAN и HC) | 10.0+ |
Зебра EC55 (WAN) | 10.0+ |
Зебра WT6300 | 10.0+ |
Скорпио X5 | 10.0+ |