Phạm vi giữa các thiết bị

Android 16 giới thiệu mô-đun Đo khoảng cách, cung cấp một giao diện hợp nhất và tiêu chuẩn để đo khoảng cách chính xác giữa các thiết bị. Bạn có thể sử dụng giao diện API này để đo khoảng cách và vị trí của các thiết bị ngang hàng mà không cần xử lý từng công nghệ đo khoảng cách riêng lẻ.

Mô-đun Ranging hỗ trợ các công nghệ sau:

Khả năng và phạm vi cung cấp

Lớp RangingManager cung cấp cho các ứng dụng thông tin về những công nghệ đo khoảng cách mà thiết bị cục bộ hỗ trợ, cũng như khả năng cung cấp và các tính năng của từng công nghệ. Các ứng dụng có thể đăng ký Callback để nhận thông tin cập nhật về mọi thay đổi đối với trạng thái hoạt động hoặc khả năng của mọi công nghệ được hỗ trợ.

Vai trò của thiết bị

Thiết bị tham gia phiên đo khoảng cách phải là thiết bị khởi tạo hoặc thiết bị phản hồi. Thiết bị khởi tạo bắt đầu phiên đo khoảng cách với một hoặc nhiều thiết bị phản hồi. Thiết bị phản hồi chỉ phản hồi các yêu cầu đo khoảng cách từ một thiết bị khởi tạo tại một thời điểm. Bạn có thể chỉ định vai trò cho một thiết bị nhất định trong phiên đo khoảng cách bằng lớp RangingPreference.

Các loại phiên

Khi bắt đầu một phiên đo khoảng cách giữa các thiết bị, bạn thường cần thiết lập một phương thức truyền dữ liệu ngoài băng tần (OOB) để trao đổi các thông số cho phiên.

Mô-đun Ranging có thể xử lý các hoạt động thương lượng OOB cho bạn, nhưng cũng hỗ trợ các hoạt động triển khai OOB tuỳ chỉnh.

Hình 1. Luồng OOB cho các loại phiên.

Triển khai OOB mặc định

Trong loại phiên này (RANGING_SESSION_OOB), mô-đun Đo khoảng cách sẽ xử lý các hoạt động thương lượng ngoài băng tần để bắt đầu một phiên đo khoảng cách. Dịch vụ này sẽ chọn các tham số phù hợp dựa trên các lựa chọn ưu tiên về phạm vi do ứng dụng cung cấp và sử dụng các công nghệ phù hợp dựa trên những gì cả hai thiết bị hỗ trợ. Loại phiên này sử dụng OOB specification tiêu chuẩn.

Mô-đun Ranging chỉ xác định định dạng và trình tự dữ liệu OOB sẽ được dùng để tương tác với một thiết bị ngang hàng. Nó không xử lý việc phát hiện thiết bị ngang hàng hoặc thiết lập kết nối.

Triển khai OOB tuỳ chỉnh

Trong loại phiên này (RANGING_SESSION_RAW), ứng dụng sẽ bỏ qua quy trình OOB của mô-đun Ranging và xử lý quy trình thương lượng OOB cũng như các tham số của riêng ứng dụng. Điều đó có nghĩa là ứng dụng phải xác định những công nghệ mà thiết bị ngang hàng hỗ trợ, thương lượng các thông số đo khoảng cách và bắt đầu phiên đo khoảng cách.

Lựa chọn ưu tiên về phạm vi

Sử dụng đối tượng RangingPreference để chỉ định các tham số đã chọn cho một phiên có phạm vi. Trong đó có:

  • Vai trò của thiết bị. Thông tin này cho biết thiết bị sẽ là thiết bị khởi tạo hay thiết bị phản hồi.
  • Cấu hình đo khoảng cách. Đối tượng RangingConfig chỉ định loại phiên trong phạm vi và các tham số khác cần thiết để bắt đầu một phiên trong phạm vi.
  • Cấu hình phiên. Đối tượng SessionConfig chỉ định các thông số sẽ được thực thi trong phiên đo khoảng cách, chẳng hạn như giới hạn đo lường, hợp nhất cảm biến, cấu hình hàng rào địa lý, v.v.

Quyền đo khoảng cách

Mô-đun Ranging (Đo khoảng cách) yêu cầu một quyền hợp nhất mới (android.permission.RANGING) để truy cập vào tất cả các công nghệ đo khoảng cách hiện tại và trong tương lai. Quyền này nằm trong danh sách NEARBY_DEVICES_PERMISSIONS.

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

Các quy định hạn chế và giới hạn

Có thể Mô-đun đo khoảng cách sẽ hạn chế đo khoảng cách vì một số lý do, bao gồm cả những lý do sau:

  • Các ứng dụng bên thứ ba chỉ được phép thực hiện tính năng đo khoảng cách ở chế độ nền bằng công nghệ siêu băng tần rộng và chỉ trên các thiết bị được hỗ trợ. Không được phép đo khoảng cách ở chế độ nền bằng các công nghệ khác.
  • Không được phép đo khoảng cách khi thiết bị đã đạt đến số lượng phiên đo khoảng cách đồng thời tối đa.
  • Phạm vi có thể bị hạn chế do các vấn đề về tình trạng của hệ thống, chẳng hạn như pin, hiệu suất hoặc bộ nhớ.

Mô-đun Ranging cũng có các hạn chế đã biết sau đây:

  • Mô-đun Ranging chỉ hỗ trợ việc phân phối dữ liệu đo khoảng cách đến các thiết bị ngang hàng cho băng tần siêu rộng. Đối với các công nghệ khác, mô-đun Đo khoảng cách chỉ cung cấp dữ liệu đo khoảng cách cho thiết bị khởi tạo.
  • Mô-đun Đo khoảng cách chỉ hỗ trợ việc thêm thiết bị một cách linh hoạt ở chế độ đo khoảng cách thô và chỉ dành cho băng tần siêu rộng.
  • Mô-đun Ranging không hỗ trợ các phiên bản băng tần siêu rộng một-đến-nhiều cho các hoạt động triển khai OOB mặc định. Nếu bạn truyền nhiều mã nhận dạng thiết bị, mô-đun sẽ tạo một phiên tương ứng cho từng thiết bị ngang hàng hỗ trợ công nghệ siêu băng tần.

Tiến hành một phiên đo khoảng cách

Để tiến hành một phiên đo khoảng cách bằng mô-đun Đo khoảng cách, hãy làm theo các bước sau:

  1. Xác minh rằng tất cả thiết bị đều đang chạy Android 16 trở lên.
  2. Yêu cầu quyền android.permission.RANGING trong tệp kê khai ứng dụng.
  3. Đánh giá khả năng và phạm vi cung cấp của các công nghệ đo khoảng cách.
  4. Khám phá một thiết bị ngang hàng cho các thao tác đo khoảng cách.
  5. Thiết lập kết nối để trao đổi ngoài băng tần, bằng cách sử dụng một trong các loại phiên được mô tả trong phần Các loại phiên đo khoảng cách.
  6. Bắt đầu đo khoảng cách và liên tục thu thập dữ liệu đo khoảng cách.
  7. Chấm dứt phiên đo khoảng cách.

Mã mẫu sau đây minh hoạ các bước này cho cả vai trò của người khởi tạo và vai trò của người phản hồi.

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

Khả năng tương tác UWB với các thiết bị iOS

Mô-đun Ranging hỗ trợ khả năng tương tác với các thiết bị iOS bằng băng tần siêu rộng (UWB). Để đo khoảng cách bằng thiết bị iOS, bạn phải sử dụng chế độ triển khai OOB tuỳ chỉnh và định cấu hình phiên đo khoảng cách bằng các thông số cụ thể khớp với Giao thức phụ kiện tương tác ở gần của Apple. Hãy tham khảo ứng dụng mẫu để biết thông tin tham khảo.

Khi tạo RangingPreference, hãy sử dụng RawRangingDeviceUwbRangingParams để chỉ định cấu hình. Các tham số sau đây là yếu tố quan trọng để tương tác với iOS:

  • Mã cấu hình: Sử dụng UwbRangingParams.CONFIG_UNICAST_DS_TWR.
  • Thông tin khoá phiên: Cung cấp một mảng byte chứa Mã nhận dạng nhà cung cấp và STS IV tĩnh.
  • Kênh phức tạp: Đặt số kênh và chỉ mục phần mở đầu sao cho khớp với cấu hình của thiết bị iOS.

Đoạn mã sau đây minh hoạ cách tạo một RangingPreference cho một thiết bị khởi tạo trong phạm vi với một thiết bị phản hồi 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();

Ứng dụng mẫu

Để xem ví dụ toàn diện về cách sử dụng mô-đun Đo khoảng cách, hãy xem ứng dụng mẫu trong AOSP. Ứng dụng mẫu này bao gồm tất cả các công nghệ đo khoảng cách mà mô-đun Đo khoảng cách hỗ trợ và bao gồm các quy trình cho cả hai loại phiên được hỗ trợ.

Khả năng tương tác UWB với các thiết bị iOS

Ứng dụng mẫu Android hỗ trợ việc bắt đầu một phiên đo khoảng cách bằng UWB với ứng dụng mẫu iOS.

Hình 2. Cách sử dụng UWB trên Android và iOS.