Android 17 में डेवलपर के लिए, कई नई सुविधाएं और एपीआई उपलब्ध कराए गए हैं. यहां दिए गए सेक्शन में, इन सुविधाओं के बारे में खास जानकारी दी गई है. इससे आपको इनसे जुड़े एपीआई का इस्तेमाल शुरू करने में मदद मिलेगी.
नए, बदले गए, और हटाए गए एपीआई की पूरी सूची देखने के लिए, एपीआई में अंतर दिखाने वाली रिपोर्ट पढ़ें. नए एपीआई के बारे में ज़्यादा जानने के लिए, Android API रेफ़रंस पर जाएं. नए एपीआई को हाइलाइट किया गया है, ताकि वे आसानी से दिख सकें.
आपको उन क्षेत्रों की भी समीक्षा करनी चाहिए जहां प्लैटफ़ॉर्म में हुए बदलावों से आपके ऐप्लिकेशन पर असर पड़ सकता है. ज़्यादा जानकारी के लिए, ये पेज देखें:
- Android 17 को टारगेट करने वाले ऐप्लिकेशन पर असर डालने वाले व्यवहार में बदलाव
- ऐसे बदलाव जिनका असर सभी ऐप्लिकेशन पर पड़ता है, भले ही वे
targetSdkVersionके हों या न हों.
मुख्य फ़ंक्शन
Android 17 में, Android की मुख्य सुविधाओं से जुड़ी ये नई सुविधाएं जोड़ी गई हैं.
ProfilingManager के नए ट्रिगर
Android 17 向 ProfilingManager 添加了多个新的系统触发器,可帮助您收集深入的数据来调试性能问题。
新增的触发条件包括:
TRIGGER_TYPE_COLD_START:触发器在应用冷启动期间触发。它会在响应中同时提供调用堆栈样本和系统轨迹。TRIGGER_TYPE_OOM:当应用抛出OutOfMemoryError并提供 Java 堆转储作为响应时,会触发此事件。TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE:当应用因 CPU 使用异常且过高而被终止时,触发器会触发,并提供调用堆栈样本作为响应。TRIGGER_TYPE_ANOMALY:检测系统性能异常,例如过多的 binder 调用和过多的内存用量。
如需了解如何设置系统触发器,请参阅有关基于触发器的分析以及如何检索和分析分析数据的文档。
应用异常的分析触发器
Android 17 引入了一项设备端异常检测服务,用于监控资源密集型行为和潜在的兼容性回归。此服务与 ProfilingManager 集成,可让您的应用接收由特定系统检测到的事件触发的分析工件。
使用 TRIGGER_TYPE_ANOMALY 触发器可检测系统性能问题,例如过多的 binder 调用和过多的内存用量。当应用超出操作系统定义的内存限制时,异常触发器可让开发者接收特定于应用的堆转储,以帮助他们识别和修复内存问题。此外,对于过多的 Binder 垃圾信息,异常触发器会在 Binder 事务上提供堆栈采样配置文件。
此 API 回调发生在任何系统强制执行之前。例如,它可以帮助开发者在应用因超出内存限制而被系统终止之前收集调试数据。
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(API 级别 37)或更高版本的设备,可提供一种注重隐私保护的替代方案,以取代范围广泛的 READ_CONTACTS 权限。您的应用无需请求访问用户的整个地址簿,而是指定所需的数据字段(例如电话号码或电子邮件地址),然后用户选择要分享的特定联系人。这只会授予您的应用对所选数据的读取权限,从而确保精细控制,同时提供一致的用户体验,并具有内置的搜索、个人资料切换和多选功能,而无需构建或维护界面。
如需了解详情,请参阅联系人选择器文档。
सुरक्षा
Android 17 में, डिवाइस और ऐप्लिकेशन की सुरक्षा को बेहतर बनाने के लिए ये नई सुविधाएं जोड़ी गई हैं.
Android का ऐडवांस सुरक्षा मोड (एएपीएम)
Android के ऐडवांस सुरक्षा मोड में, Android उपयोगकर्ताओं को सुरक्षा से जुड़ी नई सुविधाएं मिलती हैं. इससे उपयोगकर्ताओं को सुरक्षित रखने में मदद मिलती है. खास तौर पर, उन लोगों को जिनके खातों पर, ऑनलाइन हमलों का खतरा ज़्यादा होता है. AAPM को ऑप्ट-इन सुविधा के तौर पर डिज़ाइन किया गया है. इसे कॉन्फ़िगरेशन की एक सेटिंग से चालू किया जाता है. उपयोगकर्ता इसे किसी भी समय चालू कर सकते हैं, ताकि सुरक्षा से जुड़ी कुछ खास सेटिंग लागू की जा सकें.
इन मुख्य कॉन्फ़िगरेशन में, अज्ञात सोर्स से ऐप्लिकेशन इंस्टॉल करने (साइडलोडिंग) पर रोक लगाना, यूएसबी डेटा सिग्नलिंग को सीमित करना, और Google Play Protect की स्कैनिंग को ज़रूरी बनाना शामिल है. इससे डिवाइस पर हमला होने की आशंका काफ़ी कम हो जाती है.
डेवलपर, इस सुविधा को AdvancedProtectionManager एपीआई का इस्तेमाल करके इंटिग्रेट कर सकते हैं. इससे मोड की स्थिति का पता लगाया जा सकता है. इससे ऐप्लिकेशन, उपयोगकर्ता के ऑप्ट-इन करने पर सुरक्षा से जुड़ी सेटिंग को अपने-आप लागू कर सकते हैं या ज़्यादा जोखिम वाले फ़ंक्शन को सीमित कर सकते हैं.
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 音频模式的助理应用可以进一步提高音量控制的一致性。助理应用可以使用此模式向系统提供有关有效助理会话的提示,确保可以在有效 USAGE_ASSISTANT 播放之外或通过连接的蓝牙外围设备控制助理流。
हैंडऑफ़
切换是 Android 17 中即将推出的一项新功能和 API,应用开发者可以将其集成到应用中,以便为用户提供跨设备连续性。它允许用户在一台 Android 设备上启动应用 activity,然后将其过渡到另一台 Android 设备。Handoff 在用户设备的后台运行,并通过各种入口点(例如接收设备上的启动器和任务栏)显示用户附近其他设备上的可用活动。
应用可以指定 Handoff 来启动相同的原生 Android 应用(如果该应用已安装在接收设备上且可供使用)。在此应用到应用流程中,用户通过深层链接跳转到指定 activity。或者,应用到网站切换功能可以作为后备选项提供,也可以通过网址切换功能直接实现。
切换支持是按 activity 实现的。如需启用 Handoff,请针对 activity 调用 setHandoffEnabled() 方法。可能需要随切换传递额外数据,以便接收设备上重新创建的 activity 可以恢复适当的状态。实现 onHandoffActivityDataRequested() 回调以返回 HandoffActivityData 对象,该对象包含用于指定 Handoff 应如何处理并在接收设备上重新创建 activity 的详细信息。
लाइव अपडेट - सिमैंटिक कलर एपीआई
Android 17 में, लाइव अपडेट सुविधा के साथ सिमैंटिक कलरिंग एपीआई लॉन्च किए गए हैं. इनकी मदद से, ऐसे रंगों का इस्तेमाल किया जा सकता है जिनका मतलब सभी के लिए एक जैसा हो.
ये क्लास, सिमैंटिक कलरिंग के साथ काम करती हैं:
NotificationNotification.MetricNotification.ProgressStyle.PointNotification.ProgressStyle.Segment
रंग भरने से जुड़े गेम
- हरा: यह रंग सुरक्षा से जुड़ा है. इस रंग का इस्तेमाल तब किया जाना चाहिए, जब लोगों को यह बताना हो कि आप सुरक्षित हैं.
- नारंगी: इसका इस्तेमाल, चेतावनी देने और शारीरिक खतरों को मार्क करने के लिए किया जाता है. इस रंग का इस्तेमाल तब किया जाना चाहिए, जब उपयोगकर्ताओं को बेहतर सुरक्षा सेटिंग सेट करने के लिए ध्यान देने की ज़रूरत हो.
- लाल: आम तौर पर, यह खतरे या रुकने का संकेत देता है. इसे ऐसे मामलों में इस्तेमाल किया जाना चाहिए जिनमें लोगों का ध्यान तुरंत खींचना ज़रूरी हो.
- नीला: यह रंग ऐसे कॉन्टेंट के लिए इस्तेमाल किया जाता है जिसमें जानकारी दी गई हो और जिसे दूसरे कॉन्टेंट से अलग दिखाना हो.
यहां दिए गए उदाहरण में, सूचना में मौजूद टेक्स्ट पर सिमैंटिक स्टाइल लागू करने का तरीका बताया गया है:
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();