Диапазон между устройствами

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

Модуль определения дальности поддерживает следующие технологии:

Диапазон возможностей и доступности

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

роли устройств

Устройство, участвующее в сеансе измерения расстояния, должно быть либо инициатором , либо ответчиком . Устройство-инициатор начинает сеанс измерения расстояния с одним или несколькими устройствами-ответчиками. Устройство-ответчик отвечает на запросы измерения расстояния только от одного инициатора одновременно. Роль для данного устройства в сеансе измерения расстояния можно указать с помощью класса RangingPreference .

Типы сеансов измерения расстояний

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

Модуль Ranging может обрабатывать стандартные согласования (OOB-согласования) за вас, но он также поддерживает пользовательские реализации OOB-согласований.

Рисунок 1. Схема работы внеполосных процессов для различных типов сессий.

Реализация по умолчанию (OOB)

В этом типе сессии ( RANGING_SESSION_OOB ) модуль определения расстояния обрабатывает внеполосные согласования для начала сессии определения расстояния. Он выбирает подходящие параметры на основе предпочтений определения расстояния, предоставленных приложением, и использует соответствующие технологии в зависимости от того, что поддерживают оба устройства. Этот тип сессии использует стандартизированную OOB specification .

Модуль определения дальности (Ranging) определяет только формат и последовательность исходящих данных, используемых для взаимодействия с соседним устройством. Он не занимается обнаружением соседних устройств или установлением соединения.

Пользовательская реализация "из коробки"

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

Диапазон предпочтений

Для указания параметров, выбранных для сеанса измерения расстояния, используйте объект RangingPreference . К ним относятся следующие:

  • Роль устройства. Это указывает, будет ли устройство инициатором или ответчиком.
  • Настройка измерения расстояний. Объект RangingConfig определяет тип сеанса измерения расстояний и другие параметры, необходимые для начала сеанса.
  • Конфигурация сессии. Объект SessionConfig задает параметры, которые должны применяться к сессии измерения расстояния, такие как ограничение на количество измерений, объединение данных с датчиков, конфигурация геозоны и многое другое.

Разрешение на вырубку леса

Для доступа ко всем существующим и будущим технологиям определения расстояния модулю Ranging требуется новое унифицированное разрешение ( android.permission.RANGING ). Это разрешение находится в списке NEARBY_DEVICES_PERMISSIONS .

<uses-permission android:name="android.permission.RANGING" />

Ограничения и лимиты

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

  • Сторонним приложениям разрешено выполнять измерение расстояния в фоновом режиме только с использованием сверхширокополосной связи и только на поддерживаемых устройствах . Измерение расстояния в фоновом режиме с использованием других технологий не допускается.
  • Измерение расстояния не допускается, если достигнуто максимальное количество одновременных сеансов измерения расстояния устройством.
  • Дальность действия может быть ограничена из-за проблем со здоровьем системы, таких как состояние батареи, производительность или память.

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

  • Модуль определения дальности поддерживает передачу данных о дальности только на соседние устройства для сверхширокополосной связи. Для других технологий модуль определения дальности передает данные только на инициирующее устройство.
  • Модуль измерения расстояния поддерживает динамическое добавление устройств только в режиме измерения расстояния без привязки к конкретному устройству и только для сверхширокополосной связи.
  • Модуль Ranging не поддерживает сеансы сверхширокополосной связи «один ко многим» для стандартных реализаций OOB . Если вы передадите несколько дескрипторов устройств, модуль создаст сеанс «один к одному» для каждого устройства-партнера, поддерживающего сверхширокополосную связь.

Проведите замеры расстояния.

Для проведения измерения расстояния с помощью модуля «Измерение расстояния» выполните следующие шаги:

  1. Убедитесь, что все устройства работают под управлением Android 16 или более поздней версии.
  2. Укажите разрешение android.permission.RANGING в манифесте приложения.
  3. Оцените возможности и доступность технологий определения расстояния.
  4. Найдите аналогичное устройство для проведения измерений.
  5. Установите соединение для внеполосного обмена данными, используя один из типов сеансов, описанных в разделе «Типы сеансов определения дальности» .
  6. Инициируйте измерение расстояния и непрерывно собирайте данные о расстоянии.
  7. Завершить сеанс измерения расстояний.

Приведенный ниже пример кода демонстрирует эти шаги как для роли инициатора, так и для роли ответчика.

Котлин

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

Совместимость UWB с устройствами iOS

Модуль определения расстояния поддерживает взаимодействие с устройствами iOS, использующими сверхширокополосную связь (UWB). Для определения расстояния с помощью устройства iOS необходимо использовать собственную реализацию OOB и настроить сеанс определения расстояния с определенными параметрами, соответствующими протоколу Apple Nearby Interaction Accessory Protocol . Для получения дополнительной информации обратитесь к примеру приложения .

При создании RangingPreference используйте RawRangingDevice и UwbRangingParams для указания конфигурации. Следующие параметры имеют решающее значение для совместимости с iOS:

  • Идентификатор конфигурации: Используйте UwbRangingParams.CONFIG_UNICAST_DS_TWR .
  • Информация о ключе сессии: Предоставьте массив байтов, содержащий идентификатор поставщика и статический вектор инициализации STS.
  • Сложный канал: установите номер канала и индекс преамбулы в соответствии с конфигурацией устройства iOS.

Приведенный ниже фрагмент кода демонстрирует, как создать RangingPreference для определения расстояния до инициирующего устройства с помощью iOS-ответчика:

Котлин

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

Пример приложения

Полный пример использования модуля «Измерение расстояния» можно найти в демонстрационном приложении в AOSP. Это демонстрационное приложение охватывает все технологии измерения расстояния, поддерживаемые модулем «Измерение расстояния», и включает в себя сценарии для обоих поддерживаемых типов сессий.

Совместимость UWB с устройствами iOS

Демонстрационное приложение для Android поддерживает запуск сеанса измерения расстояния по протоколу UWB с помощью демонстрационного приложения для iOS .

Рисунок 2. Использование UWB в Android и iOS.