Tính năng và API

Android 17 mang đến cho nhà phát triển các tính năng và API mới tuyệt vời. Các phần sau đây tóm tắt những tính năng này để giúp bạn bắt đầu sử dụng các API liên quan.

Để biết danh sách chi tiết về các API mới, đã được sửa đổi, cũng như đã bị xoá, hãy đọc báo cáo điểm khác biệt về API. Để biết thông tin chi tiết về các API mới, vui lòng truy cập Tài liệu tham khảo API cho Android (các API mới được trình bày nổi bật).

Bạn cũng nên xem xét những khía cạnh mà thay đổi của nền tảng có thể ảnh hưởng đến ứng dụng của bạn. Để biết thêm thông tin, hãy xem các trang sau:

Chức năng cốt lõi

Android 17 bổ sung các tính năng mới sau đây liên quan đến chức năng cốt lõi của Android.

Điều kiện kích hoạt ProfilingManager mới

Android 17 bổ sung một số trình kích hoạt hệ thống mới vào ProfilingManager để giúp bạn thu thập dữ liệu chuyên sâu nhằm gỡ lỗi các vấn đề về hiệu suất.

Các điều kiện kích hoạt mới là:

  • TRIGGER_TYPE_COLD_START: Trình kích hoạt xảy ra trong quá trình khởi động nguội ứng dụng. Công cụ này cung cấp cả mẫu ngăn xếp lệnh gọi và dấu vết hệ thống trong phản hồi.
  • TRIGGER_TYPE_OOM: Trình kích hoạt xảy ra khi một ứng dụng gửi OutOfMemoryError và cung cấp một tệp báo lỗi Java Heap Dump để phản hồi.
  • TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE: Trình kích hoạt xảy ra khi một ứng dụng bị buộc dừng do mức sử dụng CPU bất thường và quá mức, đồng thời cung cấp mẫu ngăn xếp lệnh gọi để phản hồi.
  • TRIGGER_TYPE_ANOMALY: Phát hiện các điểm bất thường về hiệu suất hệ thống, chẳng hạn như các lệnh gọi liên kết quá mức và mức sử dụng bộ nhớ quá mức.

Để hiểu cách thiết lập trình kích hoạt hệ thống, hãy xem tài liệu về phân tích dựa trên trình kích hoạt và cách truy xuất và phân tích dữ liệu phân tích.

Trình kích hoạt phân tích cho các điểm bất thường của ứng dụng

Android 17 ra mắt dịch vụ phát hiện hoạt động bất thường trên thiết bị, giúp theo dõi các hành vi tiêu tốn nhiều tài nguyên và khả năng hồi quy tương thích. Được tích hợp với ProfilingManager, dịch vụ này cho phép ứng dụng của bạn nhận các cấu phần phần mềm phân tích tài nguyên do các sự kiện cụ thể mà hệ thống phát hiện được kích hoạt.

Sử dụng điều kiện kích hoạt TRIGGER_TYPE_ANOMALY để phát hiện các vấn đề về hiệu suất hệ thống, chẳng hạn như các lệnh gọi liên kết quá mức và mức sử dụng bộ nhớ quá mức. Khi một ứng dụng vượt quá giới hạn bộ nhớ do hệ điều hành xác định, trình kích hoạt điểm bất thường sẽ cho phép nhà phát triển nhận tệp báo lỗi dành riêng cho ứng dụng để giúp xác định và khắc phục các vấn đề về bộ nhớ. Ngoài ra, đối với trường hợp có quá nhiều nội dung rác trong liên kết, trình kích hoạt bất thường sẽ cung cấp hồ sơ lấy mẫu ngăn xếp về các giao dịch liên kết.

Lệnh gọi lại API này diễn ra trước khi hệ thống áp dụng bất kỳ biện pháp thực thi nào. Ví dụ: API này có thể giúp nhà phát triển thu thập dữ liệu gỡ lỗi trước khi ứng dụng bị hệ thống chấm dứt do vượt quá giới hạn bộ nhớ.

val profilingManager =
    applicationContext.getSystemService(ProfilingManager::class.java)
val triggers = ArrayList<ProfilingTrigger>()
triggers.add(ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_ANOMALY))
val mainExecutor: Executor = Executors.newSingleThreadExecutor()
val resultCallback = Consumer<ProfilingResult> { profilingResult ->
    if (profilingResult.errorCode != ProfilingResult.ERROR_NONE) {
        // upload profile result to server for further analysis
        setupProfileUploadWorker(profilingResult.resultFilePath)
    }
    profilingManager.registerForAllProfilingResults(mainExecutor,
                                                    resultCallback)
    profilingManager.addProfilingTriggers(triggers)
}

API JobDebugInfo

Android 17 ra mắt các API JobDebugInfo mới để giúp nhà phát triển gỡ lỗi các công việc JobScheduler – lý do công việc không chạy, thời gian chạy và thông tin tổng hợp khác.

Phương thức đầu tiên của API JobDebugInfo mở rộng là getPendingJobReasonStats(). Phương thức này trả về một bản đồ gồm các lý do khiến công việc ở trạng thái thực thi đang chờ xử lý và thời lượng chờ xử lý tích luỹ tương ứng. Phương thức này kết hợp các phương thức getPendingJobReasonsHistory() và getPendingJobReasons() để giúp bạn hiểu rõ lý do một công việc theo lịch không chạy như mong đợi, nhưng đơn giản hoá việc truy xuất thông tin bằng cách cung cấp cả thời lượng và lý do công việc trong một phương thức duy nhất.

Ví dụ: đối với một jobId được chỉ định, phương thức này có thể trả về PENDING_JOB_REASON_CONSTRAINT_CHARGING và thời lượng 60.000 mili giây, cho biết công việc đang chờ xử lý trong 60.000 mili giây do không đáp ứng được quy tắc ràng buộc về việc sạc.

Giảm khoá chế độ thức bằng tính năng hỗ trợ trình nghe cho chuông báo cho phép khi rảnh

Android 17 ra mắt một biến thể mới của AlarmManager.setExactAndAllowWhileIdle chấp nhận OnAlarmListener thay vì PendingIntent. Cơ chế mới dựa trên lệnh gọi lại này là lựa chọn lý tưởng cho những ứng dụng hiện dựa vào khoá chế độ thức liên tục để thực hiện các tác vụ định kỳ, chẳng hạn như ứng dụng nhắn tin duy trì kết nối cổng giao tiếp.

Quyền riêng tư

Android 17 có các tính năng mới sau đây để cải thiện quyền riêng tư của người dùng.

Hỗ trợ nền tảng Client Hello được mã hoá (ECH)

Android 17 hỗ trợ nền tảng cho Encrypted Client Hello (ECH), một tính năng cải tiến đáng kể về quyền riêng tư cho hoạt động giao tiếp qua mạng. ECH là một tiện ích TLS 1.3 mã hoá Chỉ báo tên máy chủ (SNI) trong quá trình bắt tay TLS ban đầu. Phương thức mã hoá này giúp bảo vệ quyền riêng tư của người dùng bằng cách khiến các trung gian mạng khó xác định được miền cụ thể mà một ứng dụng đang kết nối.

Giờ đây, nền tảng này bao gồm các API cần thiết để các thư viện mạng triển khai ECH. Điều này bao gồm các chức năng mới trong DnsResolver để truy vấn các bản ghi DNS HTTPS có chứa cấu hình ECH, cũng như các phương thức mới trong SSLEngine và SSLSocket của Conscrypt để bật ECH bằng cách truyền các cấu hình này khi kết nối với một miền. Nhà phát triển có thể định cấu hình các lựa chọn ưu tiên về ECH, chẳng hạn như cho phép sử dụng tuỳ ý hoặc bắt buộc sử dụng ECH, thông qua phần tử <domainEncryption> mới trong tệp Cấu hình bảo mật mạng, áp dụng trên toàn cầu hoặc theo từng miền.

Các thư viện mạng phổ biến như HttpEngine, WebView và OkHttp dự kiến sẽ tích hợp các API nền tảng này trong các bản cập nhật sau này, giúp các ứng dụng dễ dàng áp dụng ECH và nâng cao quyền riêng tư của người dùng.

Để biết thêm thông tin, hãy xem tài liệu về Encrypted Client Hello.

Bộ chọn người liên hệ của Android

Bộ chọn người liên hệ của Android là một giao diện chuẩn hoá, có thể duyệt xem để người dùng chia sẻ người liên hệ với ứng dụng của bạn. Có trên các thiết bị chạy Android 17 (API cấp 37) trở lên, bộ chọn này là một giải pháp thay thế đảm bảo quyền riêng tư cho quyền READ_CONTACTS rộng. Thay vì yêu cầu quyền truy cập vào toàn bộ sổ địa chỉ của người dùng, ứng dụng của bạn sẽ chỉ định các trường dữ liệu cần thiết (chẳng hạn như số điện thoại hoặc địa chỉ email) và người dùng sẽ chọn những người liên hệ cụ thể để chia sẻ. Thao tác này chỉ cấp cho ứng dụng của bạn quyền đọc đối với dữ liệu đã chọn, đảm bảo quyền kiểm soát thật chi tiết, đồng thời mang lại trải nghiệm người dùng nhất quán nhờ các tính năng tìm kiếm tích hợp, chuyển đổi hồ sơ trên Tìm kiếm và chọn nhiều mục mà không cần phải xây dựng hoặc duy trì giao diện người dùng.

Để biết thêm thông tin, hãy xem tài liệu về trình chọn người liên hệ.

Bảo mật

Android 17 bổ sung các tính năng mới sau đây để cải thiện khả năng bảo mật của thiết bị và ứng dụng.

Chế độ bảo vệ nâng cao trên Android (AAPM)

Chế độ Bảo vệ nâng cao của Android cung cấp cho người dùng Android một bộ tính năng bảo mật mới mạnh mẽ, đánh dấu một bước tiến quan trọng trong việc bảo vệ người dùng (đặc biệt là những người dùng có nguy cơ cao hơn) khỏi các cuộc tấn công tinh vi. Được thiết kế như một tính năng chọn sử dụng, AAPM được kích hoạt bằng một chế độ cài đặt cấu hình duy nhất mà người dùng có thể bật bất cứ lúc nào để áp dụng một bộ biện pháp bảo vệ bảo mật theo ý kiến riêng.

Các cấu hình cốt lõi này bao gồm việc chặn cài đặt ứng dụng từ các nguồn không xác định (tải ứng dụng bên ngoài), hạn chế tín hiệu dữ liệu USB và bắt buộc quét bằng Google Play Protect, giúp giảm đáng kể phạm vi tấn công của thiết bị. Nhà phát triển có thể tích hợp với tính năng này bằng cách sử dụng API AdvancedProtectionManager để phát hiện trạng thái của chế độ, cho phép các ứng dụng tự động áp dụng trạng thái bảo mật tăng cường hoặc hạn chế chức năng có rủi ro cao khi người dùng đã chọn sử dụng.

Ký APK bằng PQC

Android hiện hỗ trợ giao thức chữ ký APK kết hợp để bảo vệ danh tính ký của ứng dụng trong tương lai trước mối đe doạ tiềm ẩn từ các cuộc tấn công sử dụng điện toán lượng tử. Tính năng này ra mắt một Lược đồ chữ ký APK mới, cho phép bạn ghép nối khoá ký cổ điển (chẳng hạn như RSA hoặc EC) với một thuật toán mật mã hậu lượng tử (PQC) mới (ML-DSA).

Phương pháp kết hợp này đảm bảo ứng dụng của bạn luôn được bảo mật trước các cuộc tấn công lượng tử trong tương lai, đồng thời duy trì khả năng tương thích ngược hoàn toàn với các phiên bản Android cũ và thiết bị dựa vào quy trình xác minh chữ ký cổ điển.

Tác động đối với nhà phát triển

  • Ứng dụng sử dụng tính năng Ký ứng dụng của Play: Nếu sử dụng tính năng Ký ứng dụng của Play, bạn có thể đợi Google Play cung cấp cho bạn lựa chọn nâng cấp chữ ký kết hợp bằng khoá PQC do Google Play tạo, đảm bảo ứng dụng của bạn được bảo vệ mà không cần quản lý khoá theo cách thủ công.
  • Ứng dụng sử dụng khoá tự quản lý: Nhà phát triển tự quản lý khoá ký có thể sử dụng các công cụ cập nhật của bản dựng Android (như apksigner) để chuyển sang danh tính kết hợp, kết hợp khoá PQC với khoá cổ điển mới. (Bạn phải tạo một khoá cổ điển mới, bạn không thể sử dụng lại khoá cũ.)

Khả năng kết nối

Android 17 bổ sung các tính năng sau để cải thiện khả năng kết nối của thiết bị và ứng dụng.

Mạng vệ tinh bị hạn chế

Triển khai các hoạt động tối ưu hoá để cho phép ứng dụng hoạt động hiệu quả trên các mạng vệ tinh có băng thông thấp.

Trải nghiệm người dùng và giao diện người dùng hệ thống

Android 17 có những thay đổi sau đây để cải thiện trải nghiệm người dùng.

Luồng âm lượng riêng cho Trợ lý

Android 17 ra mắt một luồng âm lượng riêng cho Trợ lý dành cho các ứng dụng Trợ lý, để phát bằng USAGE_ASSISTANT. Thay đổi này tách biệt âm thanh của Trợ lý khỏi luồng nội dung nghe nhìn tiêu chuẩn, giúp người dùng điều chỉnh riêng biệt cả hai mức âm lượng. Điều này cho phép các trường hợp như tắt tiếng phát nội dung nghe nhìn trong khi vẫn duy trì khả năng nghe được cho các phản hồi của Trợ lý và ngược lại.

Các ứng dụng Trợ lý có quyền truy cập vào chế độ âm thanh MODE_ASSISTANT_CONVERSATION mới có thể cải thiện hơn nữa tính nhất quán của chế độ điều khiển âm lượng. Các ứng dụng Trợ lý có thể sử dụng chế độ này để gợi ý cho hệ thống về một phiên Trợ lý đang hoạt động, đảm bảo luồng Trợ lý có thể được kiểm soát bên ngoài chế độ phát USAGE_ASSISTANT đang hoạt động hoặc bằng các thiết bị ngoại vi Bluetooth đã kết nối.

Handoff

Chuyển giao là một tính năng và API mới sắp có trên Android 17 mà nhà phát triển ứng dụng có thể tích hợp để mang đến trải nghiệm liền mạch trên nhiều thiết bị cho người dùng. Tính năng này cho phép người dùng bắt đầu một hoạt động trong ứng dụng trên một thiết bị Android và chuyển hoạt động đó sang một thiết bị Android khác. Tính năng Chuyển giao chạy ở chế độ nền trên thiết bị của người dùng và hiển thị các hoạt động có sẵn trên các thiết bị khác ở gần của người dùng thông qua nhiều điểm truy cập, chẳng hạn như trình chạy và thanh tác vụ, trên thiết bị nhận.

Ứng dụng có thể chỉ định tính năng Chuyển giao để chạy cùng một ứng dụng Android gốc, nếu ứng dụng đó được cài đặt và có sẵn trên thiết bị nhận. Trong quy trình từ ứng dụng đến ứng dụng này, người dùng được liên kết sâu với hoạt động được chỉ định. Ngoài ra, bạn có thể cung cấp tính năng Chuyển giao từ ứng dụng sang web dưới dạng một phương án dự phòng hoặc triển khai trực tiếp bằng tính năng Chuyển giao URL.

Tính năng hỗ trợ chuyển giao được triển khai theo từng hoạt động. Để bật tính năng Chuyển giao, hãy gọi phương thức setHandoffEnabled() cho hoạt động. Bạn có thể cần phải chuyển thêm dữ liệu cùng với quá trình chuyển giao để hoạt động được tạo lại trên thiết bị nhận có thể khôi phục trạng thái thích hợp. Triển khai lệnh gọi lại onHandoffActivityDataRequested() để trả về đối tượng HandoffActivityData chứa thông tin chi tiết chỉ định cách Handoff xử lý và tạo lại hoạt động trên thiết bị nhận.

Live Update – Semantic color API

Với Android 17, Live Update ra mắt Semantic Coloring API để hỗ trợ màu sắc có ý nghĩa chung.

Các lớp sau đây hỗ trợ màu ngữ nghĩa:

Tô màu

  • Màu xanh lục: Liên quan đến sự an toàn. Màu này nên được dùng trong trường hợp cho mọi người biết bạn đang ở trong tình huống an toàn.
  • Màu cam: Để chỉ định sự thận trọng và đánh dấu các mối nguy hiểm về thể chất. Bạn nên sử dụng màu này trong trường hợp người dùng cần chú ý để đặt chế độ cài đặt bảo vệ tốt hơn.
  • Màu đỏ: Thường biểu thị nguy hiểm, dừng lại. Bạn nên trình bày thông tin này trong trường hợp cần mọi người chú ý ngay lập tức.
  • Màu xanh dương: Màu trung tính cho nội dung cung cấp thông tin và cần nổi bật hơn so với nội dung khác.

Ví dụ sau đây cho thấy cách áp dụng kiểu ngữ nghĩa cho văn bản trong thông báo:

  val ssb = SpannableStringBuilder()
        .append("Colors: ")
        .append("NONE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_UNSPECIFIED), 0)
        .append(", ")
        .append("INFO", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_INFO), 0)
        .append(", ")
        .append("SAFE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_SAFE), 0)
        .append(", ")
        .append("CAUTION", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_CAUTION), 0)
        .append(", ")
        .append("DANGER", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_DANGER), 0)

    Notification.Builder(context, channelId)
          .setSmallIcon(R.drawable.ic_icon)
          .setContentTitle("Hello World!")
          .setContentText(ssb)
          .setOngoing(true)
              .setRequestPromotedOngoing(true)

API TDoA đường xuống UWB cho Android 17

Tính năng đo khoảng cách theo phương pháp Chênh lệch thời gian đến của đường truyền xuống (DL-TDoA) cho phép thiết bị xác định vị trí của thiết bị so với nhiều điểm neo bằng cách đo lường thời gian đến tương đối của tín hiệu.

Đoạn mã sau đây minh hoạ cách khởi động Trình quản lý đo khoảng cách, xác minh khả năng của thiết bị và bắt đầu một phiên DL-TDoA:

Kotlin

class RangingApp {

    fun initDlTdoa(context: Context) {
        // Initialize the Ranging Manager
        val rangingManager = context.getSystemService(RangingManager::class.java)

        // Register for device capabilities
        val capabilitiesCallback = object : RangingManager.RangingCapabilitiesCallback {
            override fun onRangingCapabilities(capabilities: RangingCapabilities) {
                // Make sure Dl-TDoA is supported before starting the session
                if (capabilities.uwbCapabilities != null && capabilities.uwbCapabilities!!.isDlTdoaSupported) {
                    startDlTDoASession(context)
                }
            }
        }
        rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback)
    }

    fun startDlTDoASession(context: Context) {

        // Initialize the Ranging Manager
        val rangingManager = context.getSystemService(RangingManager::class.java)

        // Create session and configure parameters
        val executor = Executors.newSingleThreadExecutor()
        val rangingSession = rangingManager.createRangingSession(executor, RangingSessionCallback())
        val rangingRoundIndexes = byteArrayOf(0)
        val config: ByteArray = byteArrayOf() // OOB config data
        val params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes)

        val rangingDevice = RangingDevice.Builder().build()
        val rawTagDevice = RawRangingDevice.Builder()
            .setRangingDevice(rangingDevice)
            .setDlTdoaRangingParams(params)
            .build()

        val dtTagConfig = RawDtTagRangingConfig.Builder(rawTagDevice).build()

        val preference = RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
            .setSessionConfig(SessionConfig.Builder().build())
            .build()

        // Start the ranging session
        rangingSession.start(preference)
    }
}

private class RangingSessionCallback : RangingSession.Callback {
    override fun onDlTdoaResults(peer: RangingDevice, measurement: DlTdoaMeasurement) {
        // Process measurement results here
    }
}

Java

public class RangingApp {

    public void initDlTdoa(Context context) {

        // Initialize the Ranging Manager
        RangingManager rangingManager = context.getSystemService(RangingManager.class);

        // Register for device capabilities
        RangingManager.CapabilitiesCallback capabilitiesCallback = new RangingManager.RangingCapabilitiesCallback() {
            @Override
            public void onRangingCapabilities(RangingCapabilities capabilities) {
                // Make sure Dl-TDoA is supported before starting the session
                if (capabilities.getUwbCapabilities() != null && capabilities.getUwbCapabilities().isDlTdoaSupported()) {
                    startDlTDoASession(context);
                }
            }
        };
        rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback);
    }

    public void startDlTDoASession(Context context) {
        RangingManager rangingManager = context.getSystemService(RangingManager.class);

        // Create session and configure parameters
        Executor executor = Executors.newSingleThreadExecutor();
        RangingSession rangingSession = rangingManager.createRangingSession(executor, new RangingSessionCallback());
        byte[] rangingRoundIndexes = new byte[] {0};
        byte[] config = new byte[0]; // OOB config data
        DlTdoaRangingParams params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes);

        RangingDevice rangingDevice = new RangingDevice.Builder().build();
        RawRangingDevice rawTagDevice = new RawRangingDevice.Builder()
                .setRangingDevice(rangingDevice)
                .setDlTdoaRangingParams(params)
                .build();

        RawDtTagRangingConfig dtTagConfig = new RawDtTagRangingConfig.Builder(rawTagDevice).build();

        RangingPreference preference = new RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
                .setSessionConfig(new SessionConfig.Builder().build())
                .build();

        // Start the ranging session
        rangingSession.start(preference);
    }

    private static class RangingSessionCallback implements RangingSession.Callback {

        @Override
        public void onDlTdoaResults(RangingDevice peer, DlTdoaMeasurement measurement) {
            // Process measurement results here
        }
    }
}

Cấu hình ngoài băng tần (OOB)

Đoạn mã sau đây cung cấp ví dụ về dữ liệu cấu hình OOB DL-TDoA cho Wi-Fi và BLE:

Java

// Wifi Configuration
byte[] wifiConfig = {
    (byte) 0xDD, (byte) 0x2D, (byte) 0x5A, (byte) 0x18, (byte) 0xFF, // Header
    (byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
    (byte) 0x02, (byte) 0x00, // Profile ID
    (byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
    (byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
    (byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
    (byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
    (byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
    (byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
    (byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
    (byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01  // Session ID
};

// BLE Configuration
byte[] bleConfig = {
    (byte) 0x2D, (byte) 0x16, (byte) 0xF4, (byte) 0xFF, // Header
    (byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
    (byte) 0x02, (byte) 0x00, // Profile ID
    (byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
    (byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
    (byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
    (byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
    (byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
    (byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
    (byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
    (byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01  // Session ID
};

Nếu không thể sử dụng cấu hình OOB vì thiếu cấu hình này hoặc nếu cần thay đổi các giá trị mặc định không có trong cấu hình OOB, bạn có thể tạo tham số bằng DlTdoaRangingParams.Builder như trong đoạn mã sau. Bạn có thể sử dụng các tham số này thay cho DlTdoaRangingParams.createFromFiraConfigPacket():

Kotlin

val dlTdoaParams = DlTdoaRangingParams.Builder(1)
    .setComplexChannel(UwbComplexChannel.Builder()
            .setChannel(9).setPreambleIndex(10).build())
    .setDeviceAddress(deviceAddress)
    .setSessionKeyInfo(byteArrayOf(0x01, 0x02, 0x03, 0x04))
    .setRangingIntervalMillis(240)
    .setSlotDuration(UwbRangingParams.DURATION_2_MS)
    .setSlotsPerRangingRound(20)
    .setRangingRoundIndexes(byteArrayOf(0x01, 0x05))
    .build()

Java

DlTdoaRangingParams dlTdoaParams = new DlTdoaRangingParams.Builder(1)
    .setComplexChannel(new UwbComplexChannel.Builder()
            .setChannel(9).setPreambleIndex(10).build())
    .setDeviceAddress(deviceAddress)
    .setSessionKeyInfo(new byte[]{0x01, 0x02, 0x03, 0x04})
    .setRangingIntervalMillis(240)
    .setSlotDuration(UwbRangingParams.DURATION_2_MS)
    .setSlotsPerRangingRound(20)
    .setRangingRoundIndexes(new byte[]{0x01, 0x05})
    .build();