सुविधाएं और एपीआई

Android 17 में डेवलपर के लिए, कई नई सुविधाएं और एपीआई उपलब्ध कराए गए हैं. यहां दिए गए सेक्शन में, इन सुविधाओं के बारे में खास जानकारी दी गई है. इससे आपको इनसे जुड़े एपीआई का इस्तेमाल शुरू करने में मदद मिलेगी.

नए, बदले गए, और हटाए गए एपीआई की पूरी सूची देखने के लिए, एपीआई में हुए बदलावों की जानकारी देने वाली रिपोर्ट पढ़ें. नए एपीआई के बारे में ज़्यादा जानने के लिए, Android API रेफ़रंस पर जाएं. नए एपीआई को हाइलाइट किया गया है, ताकि वे आसानी से दिख सकें.

आपको उन क्षेत्रों की भी समीक्षा करनी चाहिए जहां प्लैटफ़ॉर्म में हुए बदलावों से आपके ऐप्लिकेशन पर असर पड़ सकता है. ज़्यादा जानकारी के लिए, ये पेज देखें:

मुख्य फ़ंक्शन

Android 17 में, Android की मुख्य सुविधाओं से जुड़ी ये नई सुविधाएं जोड़ी गई हैं.

ProfilingManager के नए ट्रिगर

Android 17 में, ProfilingManager में कई नए सिस्टम ट्रिगर जोड़े गए हैं. इनकी मदद से, परफ़ॉर्मेंस से जुड़ी समस्याओं को डीबग करने के लिए, अहम डेटा इकट्ठा किया जा सकता है.

नए ट्रिगर ये हैं:

  • TRIGGER_TYPE_COLD_START: यह ट्रिगर, ऐप्लिकेशन के कोल्ड स्टार्ट के दौरान चालू होता है. यह जवाब में, कॉल स्टैक का सैंपल और सिस्टम ट्रेस, दोनों उपलब्ध कराता है.
  • TRIGGER_TYPE_OOM: यह ट्रिगर तब चालू होता है, जब कोई ऐप्लिकेशन OutOfMemoryError दिखाता है. साथ ही, जवाब में Java Heap Dump उपलब्ध कराता है.
  • TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE: यह ट्रिगर तब चालू होता है, जब किसी ऐप्लिकेशन को सीपीयू के असामान्य और ज़्यादा इस्तेमाल की वजह से बंद कर दिया जाता है. साथ ही, जवाब में कॉल स्टैक का सैंपल उपलब्ध कराता है.
  • TRIGGER_TYPE_ANOMALY: इससे सिस्टम की परफ़ॉर्मेंस से जुड़ी गड़बड़ियों का पता लगाया जा सकता है. जैसे, बाइंडर कॉल की संख्या ज़्यादा होना और मेमोरी का ज़्यादा इस्तेमाल होना.

सिस्टम ट्रिगर सेट अप करने का तरीका जानने के लिए, ट्रिगर पर आधारित प्रोफ़ाइलिंग और प्रोफ़ाइलिंग डेटा को वापस पाने और उसका विश्लेषण करने के तरीके से जुड़ा दस्तावेज़ देखें.

ऐप्लिकेशन में गड़बड़ियों की प्रोफ़ाइलिंग करने वाला ट्रिगर

Android 17 में, डिवाइस पर गड़बड़ी का पता लगाने वाली एक सेवा शुरू की गई है. यह सेवा, ज़्यादा संसाधनों का इस्तेमाल करने वाले व्यवहार और संभावित कंपैटिबिलिटी रिग्रेशन पर नज़र रखती है. ProfilingManager के साथ इंटिग्रेट की गई इस सेवा की मदद से, आपका ऐप्लिकेशन, सिस्टम से पता लगाए गए खास इवेंट की वजह से ट्रिगर होने वाले प्रोफ़ाइलिंग आर्टफ़ैक्ट पा सकता है.

TRIGGER_TYPE_ANOMALY ट्रिगर का इस्तेमाल करके, सिस्टम की परफ़ॉर्मेंस से जुड़ी समस्याओं का पता लगाया जा सकता है. जैसे, बाइंडर कॉल की संख्या ज़्यादा होना और मेमोरी का ज़्यादा इस्तेमाल होना. जब कोई ऐप्लिकेशन, ओएस की तय की गई मेमोरी की सीमाओं को तोड़ता है, तो गड़बड़ी का पता लगाने वाला ट्रिगर, डेवलपर को ऐप्लिकेशन के लिए खास Heap Dumps पाने की अनुमति देता है. इससे उन्हें मेमोरी से जुड़ी समस्याओं की पहचान करने और उन्हें ठीक करने में मदद मिलती है. इसके अलावा, बाइंडर स्पैम की संख्या ज़्यादा होने पर, गड़बड़ी का पता लगाने वाला ट्रिगर, बाइंडर लेन-देन पर स्टैक सैंपलिंग प्रोफ़ाइल उपलब्ध कराता है.

एपीआई कॉलबैक, सिस्टम की ओर से लागू किए गए किसी भी एनफ़ोर्समेंट से पहले होता है. उदाहरण के लिए, इससे डेवलपर को डीबग डेटा इकट्ठा करने में मदद मिल सकती है. यह डेटा, ऐप्लिकेशन को मेमोरी की सीमाओं से ज़्यादा इस्तेमाल करने की वजह से सिस्टम से बंद किए जाने से पहले इकट्ठा किया जा सकता है.

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

JobDebugInfo API

Android 17 引入了新的 JobDebugInfo API,可帮助开发者调试其 JobScheduler 作业,了解作业未运行的原因、运行时长以及其他汇总信息。

扩展后的 JobDebugInfo API 的第一个方法是 getPendingJobReasonStats(),该方法会返回一个映射,其中包含作业处于待执行状态的原因及其各自的累计待执行时长。此方法将 getPendingJobReasonsHistory()getPendingJobReasons() 方法联接在一起,可让您了解预定作业未按预期运行的原因,但通过在单个方法中同时提供时长和作业原因,简化了信息检索。

例如,对于指定的 jobId,该方法可能会返回 PENDING_JOB_REASON_CONSTRAINT_CHARGING 和 60000 毫秒的时长,表示作业因未满足充电约束而处于等待状态 60000 毫秒。

allow-while-idle अलार्म के लिए लिसनर की सुविधा का इस्तेमाल करके, वेक लॉक कम करें

Android 17 में, AlarmManager.setExactAndAllowWhileIdle का नया वैरिएंट पेश किया गया है. यह PendingIntent के बजाय OnAlarmListener को स्वीकार करता है. यह नया कॉलबैक-आधारित सिस्टम, उन ऐप्लिकेशन के लिए सबसे सही है जो समय-समय पर टास्क पूरे करने के लिए, लगातार वेकलॉक पर निर्भर रहते हैं. जैसे, सॉकेट कनेक्शन बनाए रखने वाले मैसेजिंग ऐप्लिकेशन.

निजता

Android 17 में, उपयोगकर्ता की निजता को बेहतर बनाने के लिए ये नई सुविधाएं शामिल हैं.

Encrypted Client Hello (ECH) प्लैटफ़ॉर्म के लिए सहायता

Android 17 引入了对加密客户端 Hello (ECH) 的平台支持,这是对网络通信的一项重大隐私增强功能。ECH 是一项 TLS 1.3 扩展,可在初始 TLS 握手期间加密服务器名称指示 (SNI)。这种加密有助于保护用户隐私,因为它可以让网络中介更难识别应用连接到的特定网域。

该平台现在包含网络库实现 ECH 所需的 API。这包括 DnsResolver 中的新功能,用于查询包含 ECH 配置的 HTTPS DNS 记录;以及 Conscrypt 的 SSLEngine 和 SSLSocket 中的新方法,用于在连接到网域时传入这些配置来启用 ECH。开发者可以通过网络安全配置文件中的新 <domainEncryption> 元素来配置 ECH 偏好设置,例如机会性地启用 ECH 或强制使用 ECH,这些设置可全局应用,也可按网域应用。

预计 HttpEngine、WebView 和 OkHttp 等热门联网库将在未来的更新中集成这些平台 API,从而使应用能够更轻松地采用 ECH 并增强用户隐私保护。

如需了解详情,请参阅加密的客户端 Hello 文档。

Android कॉन्टैक्ट पिकर

Android कॉन्टैक्ट पिकर, एक स्टैंडर्ड इंटरफ़ेस है. इससे उपयोगकर्ता, आपके ऐप्लिकेशन के साथ कॉन्टैक्ट शेयर कर सकते हैं. यह Android 17 (एपीआई लेवल 37) या इसके बाद के वर्शन पर काम करने वाले डिवाइसों पर उपलब्ध है. यह पिकर, READ_CONTACTS अनुमति के मुकाबले ज़्यादा सुरक्षित विकल्प है. उपयोगकर्ता की पूरी पता पुस्तिका का ऐक्सेस मांगने के बजाय, आपका ऐप्लिकेशन उन डेटा फ़ील्ड के बारे में बताता है जिनकी उसे ज़रूरत है. जैसे, फ़ोन नंबर या ईमेल पते. इसके बाद, उपयोगकर्ता शेयर करने के लिए कुछ खास संपर्क चुनता है. इससे आपके ऐप्लिकेशन को सिर्फ़ चुने गए डेटा को पढ़ने का ऐक्सेस मिलता है. इससे आपको बेहतर कंट्रोल मिलता है. साथ ही, आपको एक जैसा उपयोगकर्ता अनुभव मिलता है. इसमें खोज करने, प्रोफ़ाइल स्विच करने, और एक से ज़्यादा आइटम चुनने की सुविधाएं शामिल होती हैं. इसके लिए, आपको यूज़र इंटरफ़ेस (यूआई) बनाने या उसे बनाए रखने की ज़रूरत नहीं होती.

ज़्यादा जानकारी के लिए, संपर्क चुनने वाले टूल का दस्तावेज़ देखें.

सुरक्षा

Android 17 में, डिवाइस और ऐप्लिकेशन की सुरक्षा को बेहतर बनाने के लिए ये नई सुविधाएं जोड़ी गई हैं.

Android का ऐडवांस सुरक्षा मोड (एएपीएम)

Android 高级保护模式为 Android 用户提供了一套强大的新安全功能,标志着在保护用户(尤其是面临较高风险的用户)免遭复杂攻击方面迈出了重要一步。AAPM 是一项选择启用功能,只需进行一项配置设置即可激活。用户可以随时启用该功能,以应用一套主观的安全保护措施。

这些核心配置包括:禁止安装未知来源的应用(旁加载)、限制 USB 数据信号传输,以及强制执行 Google Play 保护机制扫描,从而显著减小设备的攻击面。 开发者可以使用 AdvancedProtectionManager API 与此功能集成,以检测模式的状态,从而使应用能够在用户选择启用此模式时自动采用强化型安全姿态或限制高风险功能。

PQC APK Signing

Android अब हाइब्रिड APK सिग्नेचर स्कीम के साथ काम करता है. इससे आपके ऐप्लिकेशन की साइनिंग आइडेंटिटी को, क्वांटम कंप्यूटिंग का इस्तेमाल करके किए जाने वाले हमलों के संभावित खतरे से सुरक्षित रखने में मदद मिलती है. इस सुविधा में, नई APK सिग्नेचर स्कीम पेश की गई है. इसकी मदद से, क्लासिकल साइनिंग की (जैसे कि आरएसए या ईसी) को पोस्ट-क्वांटम क्रिप्टोग्राफ़ी (पीक्यूसी) के नए एल्गोरिदम (एमएल-डीएसए) के साथ जोड़ा जा सकता है.

इस हाइब्रिड अप्रोच से, यह पक्का किया जाता है कि आपका ऐप्लिकेशन, आने वाले समय में होने वाले क्वांटम हमलों से सुरक्षित रहे. साथ ही, यह पुराने Android वर्शन और क्लासिकल सिग्नेचर की पुष्टि करने वाले डिवाइसों के साथ पूरी तरह से काम करता रहे.

डेवलपर पर असर

  • Play ऐप्लिकेशन साइनिंग का इस्तेमाल करने वाले ऐप्लिकेशन: अगर Play ऐप्लिकेशन साइनिंग का इस्तेमाल किया जाता है, तो Google Play से जनरेट की गई पीक्यूसी कुंजी का इस्तेमाल करके, हाइब्रिड सिग्नेचर को अपग्रेड करने के विकल्प के लिए इंतज़ार किया जा सकता है. इससे यह पक्का किया जा सकता है कि आपके ऐप्लिकेशन को सुरक्षित रखा गया है. इसके लिए, आपको मैन्युअल तरीके से कुंजी को मैनेज करने की ज़रूरत नहीं होगी.
  • खुद मैनेज किए गए पासकोड का इस्तेमाल करने वाले ऐप्लिकेशन: जो डेवलपर अपने साइनिंग पासकोड मैनेज करते हैं वे अपडेट किए गए Android बिल्ड टूल (जैसे, apksigner) का इस्तेमाल करके, हाइब्रिड आइडेंटिटी पर स्विच कर सकते हैं. इसके लिए, उन्हें पीक्यूसी पासकोड को नए क्लासिकल पासकोड के साथ जोड़ना होगा. (आपको नई क्लासिकल कुंजी बनानी होगी. पुरानी कुंजी का फिर से इस्तेमाल नहीं किया जा सकता.)

कनेक्टिविटी

Android 17 में, डिवाइस और ऐप्लिकेशन की कनेक्टिविटी को बेहतर बनाने के लिए ये सुविधाएं जोड़ी गई हैं.

सैटलाइट नेटवर्क की उपलब्धता सीमित होना

इस वर्शन को इस तरह से ऑप्टिमाइज़ किया गया है, ताकि ऐप्लिकेशन कम बैंडविथ वाले सैटलाइट नेटवर्क पर भी असरदार तरीके से काम कर सकें.

उपयोगकर्ता अनुभव और सिस्टम यूज़र इंटरफ़ेस (यूआई)

Android 17 में, उपयोगकर्ता अनुभव को बेहतर बनाने के लिए ये बदलाव किए गए हैं.

Assistant की आवाज़ के लिए अलग वॉल्यूम स्ट्रीम

Android 17 为 Google 助理应用引入了专用的 Google 助理音量流, 以便使用 USAGE_ASSISTANT 进行播放。此项更改将 Google 助理音频与标准媒体流分离,让用户可以单独控制这两个音量。这样便可实现以下场景:将媒体播放静音,同时保持 Google 助理响应的可听性,反之亦然。

有权访问新的 MODE_ASSISTANT_CONVERSATION 音频模式的 Google 助理应用可以进一步提高音量控制的一致性。Google 助理应用可以使用此模式向系统提供有关活跃 Google 助理会话的提示,确保可以在活跃 USAGE_ASSISTANT 播放之外或使用连接的蓝牙外设控制 Google 助理流。

हैंडऑफ़

切换是 Android 17 中新增的一项功能和 API,应用开发者可以将其集成到应用中,以便为用户提供跨设备连续性。它允许用户在一个 Android 设备上启动应用 activity,然后将其转移到另一个 Android 设备。Handoff 在用户设备的后台运行,并通过各种入口点(例如接收设备上的启动器和任务栏)显示用户附近其他设备上的可用活动。

应用可以指定 Handoff 来启动相同的原生 Android 应用(如果该应用已安装在接收设备上且可供使用)。在此应用到应用流程中,用户通过深层链接跳转到指定 activity。或者,应用到网站切换功能可以作为后备选项提供,也可以通过网址切换功能直接实现。

切换支持是按 activity 实现的。如需启用 Handoff,请针对 activity 调用 setHandoffEnabled() 方法。可能需要随切换传递其他数据,以便接收设备上重新创建的 activity 可以恢复适当的状态。实现 onHandoffActivityDataRequested() 回调以返回 HandoffActivityData 对象,该对象包含用于指定 Handoff 应如何处理并在接收设备上重新创建 activity 的详细信息。

लाइव अपडेट - सिमैंटिक कलर एपीआई

在 Android 17 中,实时更新启动了语义着色 API,以支持具有通用含义的颜色。

以下类支持语义着色:

填色游戏

  • 绿色:与安全相关。此颜色应在以下情况下使用:让别人知道您处于安全状态。
  • 橙色:用于表示警告和标记物理危险。在用户需要注意以设置更好的保护设置的情况下,应使用此颜色。
  • 红色:通常表示危险、停止。它应在需要人们紧急关注的情况下显示。
  • 蓝色:中性颜色,适用于信息性内容,应与其他内容区分开来。

以下示例展示了如何将语义样式应用于通知中的文本:

  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)

Android 17 के लिए UWB Downlink-TDoA API

下行链路到达时间差 (DL-TDoA) 测距技术可让设备通过测量信号的相对到达时间来确定其相对于多个锚点的位置。

以下代码段演示了如何初始化 Ranging Manager、验证设备功能并启动 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
        }
    }
}

带外 (OOB) 配置

以下代码段提供了 Wi-Fi 和 BLE 的 DL-TDoA OOB 配置数据示例:

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

如果您无法使用 OOB 配置(因为缺少该配置),或者需要更改不在 OOB 配置中的默认值,则可以使用 DlTdoaRangingParams.Builder 构建参数,如以下代码段所示。您可以使用以下参数代替 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();