В Android 16 появился модуль Ranging, который предоставляет унифицированный и стандартизированный интерфейс для точного определения расстояния между устройствами. Вы можете использовать этот API для измерения расстояния и положения одноранговых устройств без необходимости обрабатывать каждую технологию определения дальности по отдельности.
Модуль Ranging поддерживает следующие технологии:
- Сверхширокополосная связь
- Зондирование каналов Bluetooth
- Wi-Fi NAN RTT
- Определение расстояния по RSSI Bluetooth
Возможности и доступность функции
Класс RangingManager предоставляет приложениям информацию о технологиях определения расстояния, поддерживаемых локальным устройством, а также о доступности и возможностях каждой технологии. Приложения могут зарегистрироваться для получения Callback, чтобы получать обновления о любых изменениях в доступности или возможностях поддерживаемых технологий.
Роли устройств
Устройство, участвующее в сеансе определения расстояния, должно быть либо инициатором, либо ответчиком. Устройство-инициатор начинает сеанс измерения расстояния с одним или несколькими устройствами-ответчиками. Устройство-ответчик отвечает на запросы измерения расстояния только от одного инициатора за раз. Вы можете указать роль для определенного устройства в сеансе измерения расстояния с помощью класса RangingPreference.
Типы сеансов определения расстояния
При запуске сеанса определения расстояния между устройствами часто требуется установить внеполосную передачу данных для обмена параметрами сеанса.
Модуль Ranging может выполнять согласование OOB за вас, но он также поддерживает пользовательские реализации OOB.
Реализация OOB по умолчанию
В сеансе этого типа (RANGING_SESSION_OOB) модуль Ranging обрабатывает согласования OOB, чтобы начать сеанс дальнометрии. Он выбирает подходящие параметры на основе настроек дальнометрии, заданных приложением, и использует технологии, которые поддерживаются обоими устройствами. В этом типе сеанса используется стандартизированный OOB specification.
Модуль Ranging определяет только формат данных и последовательность, которые будут использоваться для взаимодействия с одноранговым устройством. Он не отвечает за обнаружение одноранговых устройств или установление соединения.
Собственная реализация OOB
В сеансе этого типа (RANGING_SESSION_RAW) приложение обходит OOB-процесс модуля Ranging и самостоятельно обрабатывает OOB-согласование и параметры. Это означает, что приложение должно определить, какие технологии поддерживает одноранговое устройство, согласовать параметры измерения расстояния и начать сеанс измерения расстояния.
Настройки определения расстояния
Чтобы указать выбранные параметры для сеанса определения расстояния, используйте объект RangingPreference. Примеры:
- Роль устройства. Это указывает, будет ли устройство инициатором или ответчиком.
- Настройка определения расстояния. Объект
RangingConfigуказывает тип сеанса определения расстояния и другие параметры, необходимые для его запуска. - Настройки сеанса. Объект
SessionConfigзадает параметры, которые должны применяться к сеансу определения расстояния, например ограничение измерений, объединение датчиков, конфигурацию геозоны и т. д.
Разрешение на определение расстояния
Для доступа ко всем текущим и будущим технологиям определения расстояния модулю Ranging требуется новое единое разрешение (android.permission.RANGING). Это разрешение находится в списке NEARBY_DEVICES_PERMISSIONS.
<uses-permission android:name="android.permission.RANGING" />
Ограничения
Модуль Ranging может ограничивать дальнометрию по нескольким причинам, в том числе по следующим:
- Сторонним приложениям разрешено выполнять фоновое измерение расстояния с помощью сверхширокополосной связи только на поддерживаемых устройствах. Определение расстояния в фоновом режиме с помощью других технологий не допускается.
- Определение расстояния не разрешено, если достигнуто максимальное количество одновременных сеансов определения расстояния на устройстве.
- Определение расстояния может быть ограничено из-за проблем с системой, например с батареей, производительностью или памятью.
У модуля Ranging также есть следующие известные ограничения:
- Модуль Ranging поддерживает передачу данных о расстоянии только на одноранговые устройства со сверхширокополосной связью. Для других технологий модуль Ranging передает данные о расстоянии только на устройство-инициатор.
- Модуль Ranging поддерживает динамическое добавление устройств только в режиме необработанных данных и только для сверхширокополосной связи.
- Модуль Ranging не поддерживает сеансы сверхширокополосной связи "один ко многим" для реализаций OOB по умолчанию. Если вы передадите несколько дескрипторов устройств, модуль создаст сеанс один на один для каждого однорангового устройства, поддерживающего сверхширокополосную связь.
Проведение сеанса ранжирования
Чтобы провести сеанс измерения расстояния с помощью модуля Ranging, выполните следующие действия:
- Убедитесь, что на всех устройствах установлена ОС Android 16 или более поздней версии.
- Запросите разрешение
android.permission.RANGINGв манифесте приложения. - Оцените возможности и доступность технологий определения расстояния.
- Обнаружение однорангового устройства для определения расстояния.
- Установите соединение для внеполосного обмена данными, используя один из типов сеансов, описанных в разделе Типы сеансов измерения расстояния.
- Запускать измерение расстояния и непрерывно получать данные о расстоянии.
- Завершить сеанс определения расстояния.
В приведенном ниже примере кода показано, как выполнить эти действия для ролей инициатора и ответчика.
Kotlin
class RangingApp {
// Starts a ranging session on the initiator side.
fun startRangingInitiator(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
val config = OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build()
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build()
// Start ranging session.
session.start(preference)
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop()
}
// Starts a ranging session on the responder side.
fun startRangingResponder(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
val config = OobResponderRangingConfig.Builder(deviceHandle).build()
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build()
// Start the ranging session.
session.start(preference)
// Stop the ranging session
session.stop()
}
}
Java
public class RangingApp {
// Starts a ranging session on the initiator side.
void startRangingInitiator(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
OobInitiatorRangingConfig config = new OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build();
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build();
// Start ranging session.
session.start(preference);
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop();
}
// Starts a ranging session on the responder side.
void startRangingResponder(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
OobResponderRangingConfig config = new OobResponderRangingConfig.Builder( deviceHandle).build();
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build();
// Start the ranging session.
session.start(preference);
// Stop the ranging session
session.stop();
}
}
Совместимость СШП с устройствами iOS
Модуль Ranging поддерживает совместимость с iOS-устройствами, использующими сверхширокополосную связь (UWB). Чтобы измерить расстояние до iOS-устройства, необходимо использовать собственную реализацию OOB и настроить сеанс измерения расстояния с определенными параметрами, соответствующими протоколу Apple Nearby Interaction Accessory Protocol. Пример реализации можно посмотреть в примере приложения.
При создании RangingPreference используйте RawRangingDevice и UwbRangingParams, чтобы задать конфигурацию. Для совместимости с iOS важны следующие параметры:
- Идентификатор конфигурации. Используйте
UwbRangingParams.CONFIG_UNICAST_DS_TWR. - Информация о сеансовом ключе. Укажите массив байтов, содержащий идентификатор поставщика и статический вектор инициализации STS.
- Complex Channel (Сложный канал). Укажите номер канала и индекс преамбулы, соответствующие конфигурации iOS-устройства.
В следующем фрагменте кода показано, как создать RangingPreference для устройства-инициатора, которое определяет расстояние до устройства-ответчика iOS:
Kotlin
// Create UwbRangingParams with iOS-specific configuration
val uwbRangingParams = UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress
)
.setComplexChannel(
UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build()
)
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build()
// Create RawRangingDevice
val rawRangingDevice = RawRangingDevice.Builder()
.setRangingDevice(RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build()
// Create SessionConfig
val sessionConfig = SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build()
// Create RangingPreference for the initiator
val preference = RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build()
)
.setSessionConfig(sessionConfig)
.build()
Java
// Create UwbRangingParams with iOS-specific configuration
UwbRangingParams uwbRangingParams = new UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress)
.setComplexChannel(new UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build())
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build();
// Create RawRangingDevice
RawRangingDevice rawRangingDevice = new RawRangingDevice.Builder()
.setRangingDevice(new RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build();
// Create SessionConfig
SessionConfig sessionConfig = new SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(new DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build();
// Create RangingPreference for the initiator
RangingPreference preference = new RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
new RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build())
.setSessionConfig(sessionConfig)
.build();
UWB Downlink-TDoA API
Подробнее о новых функциях Android 17…
Пример приложения
Пример использования модуля Ranging можно найти в примере приложения в AOSP. В этом примере приложения рассматриваются все технологии определения расстояния, поддерживаемые модулем Ranging, и включены потоки для обоих поддерживаемых типов сеансов.
Совместимость СШП с устройствами iOS
Пример приложения для Android поддерживает запуск сеанса измерения расстояния с помощью СШП с примером приложения для iOS.