Вы можете использовать функцию определения местоположения 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
Wi-Fi RTT был представлен в Android 9 (уровень API 28). При использовании этого протокола для определения положения устройства с помощью мультилатерации с устройствами под управлением Android 9 вам необходимо иметь доступ к заранее определенным данным о местоположении точек доступа (AP) в вашем приложении. Вам решать, как хранить и извлекать эти данные.
На устройствах под управлением Android 10 (уровень API 29) и выше данные о местоположении точки доступа могут быть представлены в виде объектов ResponderLocation
, которые включают широту, долготу и высоту. Для точек доступа Wi-Fi RTT, которые поддерживают информацию о конфигурации местоположения/информационный отчет о местоположении (данные LCI/LCR), протокол будет возвращать объект ResponderLocation
во время процесса определения диапазона .
Эта функция позволяет приложениям напрямую запрашивать точки доступа, чтобы узнать их местоположение, вместо того, чтобы хранить эту информацию заранее. Таким образом, ваше приложение может находить точки доступа и определять их позиции, даже если точки доступа ранее не были известны, например, когда пользователь входит в новое здание.
Требования
- Аппаратное обеспечение устройства, отправляющего запрос ранжирования, должно соответствовать стандарту 802.11-2016 FTM.
- Устройство, отправляющее запрос ранжирования, должно работать под управлением Android 9 (уровень API 28) или более поздней версии.
- На устройстве, отправляющем запрос на определение диапазона, должны быть включены службы определения местоположения и включено сканирование Wi-Fi (в разделе «Настройки» > «Местоположение» ).
- Если приложение, выполняющее запрос ранжирования, предназначено для Android 13 (уровень API 33) или более поздней версии, оно должно иметь разрешение
NEARBY_WIFI_DEVICES
. Если такое приложение предназначено для более ранней версии Android, вместо этого оно должно иметь разрешениеACCESS_FINE_LOCATION
. - Приложение должно запрашивать диапазон точек доступа, пока приложение видимо или находится в службе переднего плана. Приложение не может получить доступ к информации о местоположении в фоновом режиме .
- Точка доступа должна соответствовать стандарту IEEE 802.11-2016 FTM.
Настраивать
Чтобы настроить приложение для использования 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, которым запрашивается диапазон. В одном запросе ранжирования можно указать несколько точек доступа или одноранговых узлов с поддержкой Wi-Fi; расстояния до всех устройств измеряются и возвращаются.
Например, запрос может использовать метод 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
Аналогично, запрос ранжирования может добавить узел 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. Получайте результаты для каждого успешного измерения.
Для каждого успешного измерения вы можете получить значения результатов с помощью соответствующих методов get
:
Расстояние в мм и стандартное отклонение измерения:
RSSI пакетов, использованных для измерений:
Время в миллисекундах, когда было выполнено измерение (с указанием времени с момента загрузки):
Количество предпринятых измерений и количество успешных измерений (и на которых основаны измерения расстояния):
Устройства Android, поддерживающие WiFi-RTT
В таблицах ниже перечислены некоторые телефоны , точки доступа и устройства розничной торговли, складов и распределительных центров , поддерживающие Wi-Fi-RTT. Они далеки от всеобъемлющих. Мы рекомендуем вам связаться с нами и разместить здесь список ваших продуктов с поддержкой RTT.
Точки доступа
Производитель и модель | Дата поддержки |
---|---|
Nest Wi-Fi Pro (Wi-Fi 6E) | Поддерживается |
Компулаб ДИКИЙ АП | Поддерживается |
Гугл Wi-Fi | Поддерживается |
Google Nest Wi-Fi-роутер | Поддерживается |
Точка Wi-Fi Google Nest | Поддерживается |
Аруба AP-635 | Поддерживается |
Сиско 9130 | Поддерживается |
Сиско 9136 | Поддерживается |
Сиско 9166 | Поддерживается |
Сиско 9164 | Поддерживается |
Аруба AP-505 | Поддерживается |
Аруба AP-515 | Поддерживается |
Аруба AP-575 | Поддерживается |
Аруба AP-518 | Поддерживается |
Аруба AP-505H | Поддерживается |
Аруба AP-565 | Поддерживается |
Аруба AP-535 | Поддерживается |
Телефоны
Производитель и модель | Версия Android |
---|---|
Пиксель 6 | 9.0+ |
Пиксель 6 Про | 9.0+ |
Пиксель 5 | 9.0+ |
Пиксель 5а | 9.0+ |
Пиксель 5а 5G | 9.0+ |
Сяоми Ми 10 Про | 9.0+ |
Сяоми Ми 10 | 9.0+ |
Сяоми Редми Ми 9Т Про | 9.0+ |
Сяоми Ми 9Т | 9.0+ |
Сяоми Ми 9 | 9.0+ |
Сяоми Ми Примечание 10 | 9.0+ |
Сяоми Ми Примечание 10 Лайт | 9.0+ |
Сяоми Редми Примечание 9S | 9.0+ |
Сяоми Редми Примечание 9 Про | 9.0+ |
Сяоми Редми Примечание 8Т | 9.0+ |
Сяоми Редми Примечание 8 | 9.0+ |
Сяоми Редми К30 Про | 9.0+ |
Сяоми Редми К20 Про | 9.0+ |
Сяоми Редми К20 | 9.0+ |
Сяоми Редми Примечание 5 Про | 9.0+ |
Сяоми Ми CC9 Про | 9.0+ |
LG G8X ThinQ | 9.0+ |
LG V50S ThinQ | 9.0+ |
LG V60 ThinQ | 9.0+ |
LG V30 | 9.0+ |
Samsung Галактика Ноут 10+ 5G | 9.0+ |
Самсунг Галакси С20+ 5G | 9.0+ |
Самсунг Галакси С20+ | 9.0+ |
Самсунг Галакси С20 5G | 9.0+ |
Samsung Галактика С20 Ультра 5G | 9.0+ |
Самсунг Галакси С20 | 9.0+ |
Самсунг Галакси Ноут 10+ | 9.0+ |
Samsung Галактика Примечание 10 5G | 9.0+ |
Самсунг Галакси Примечание 10 | 9.0+ |
Самсунг А9 Про | 9.0+ |
Гугл Пиксель 4 XL | 9.0+ |
Гугл Пиксель 4 | 9.0+ |
Гугл Пиксель 4а | 9.0+ |
Гугл Пиксель 3 XL | 9.0+ |
Гугл Пиксель 3 | 9.0+ |
Гугл Пиксель 3а XL | 9.0+ |
Гугл Пиксель 3а | 9.0+ |
Гугл Пиксель 2 XL | 9.0+ |
Гугл Пиксель 2 | 9.0+ |
Гугл Пиксель 1 XL | 9.0+ |
Гугл Пиксель 1 | 9.0+ |
Поко Х2 | 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 (глобальная сеть) | 10.0+ |
Зебра WT6300 | 10.0+ |
Скорпион X5 | 10.0+ |