Funktionen und APIs

Android 17 bietet Entwicklern tolle neue Funktionen und APIs. In den folgenden Abschnitten werden diese Funktionen zusammengefasst, um Ihnen den Einstieg in die zugehörigen APIs zu erleichtern.

Eine detaillierte Liste der neuen, geänderten und entfernten APIs findest du im API-Diff-Bericht. Details zu neuen APIs findest du in der Android API-Referenz. Neue APIs sind hervorgehoben.

Außerdem sollten Sie sich Bereiche ansehen, in denen sich Plattformänderungen auf Ihre Apps auswirken könnten. Weitere Informationen finden Sie auf den folgenden Seiten:

Hauptfunktion

Android 17 bietet die folgenden neuen Funktionen im Zusammenhang mit den Kernfunktionen von Android.

Neue ProfilingManager-Trigger

In Android 17 werden ProfilingManager mehrere neue Systemtrigger hinzugefügt, mit denen Sie detaillierte Daten zur Fehlerbehebung bei Leistungsproblemen erfassen können.

Die neuen Trigger sind:

  • TRIGGER_TYPE_COLD_START: Der Trigger wird während des Kaltstarts der App ausgelöst. Sie enthält sowohl ein Aufrufstackbeispiel als auch eine Ablaufverfolgung in der Antwort.
  • TRIGGER_TYPE_OOM: Der Trigger wird ausgelöst, wenn eine App einen OutOfMemoryError auslöst und als Antwort einen Java-Heap-Dump bereitstellt.
  • TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE: Der Trigger wird ausgelöst, wenn eine App aufgrund einer abnormalen und übermäßigen CPU-Auslastung beendet wird. Als Antwort wird ein Aufrufstapel-Beispiel bereitgestellt.
  • TRIGGER_TYPE_ANOMALY: Anomalien bei der Systemleistung erkennen, z. B. übermäßige Binder-Aufrufe und übermäßige Arbeitsspeichernutzung.

Informationen zum Einrichten des Systemtriggers finden Sie in der Dokumentation zum triggerbasierten Profiling und zum Abrufen und Analysieren von Profiling-Daten.

Profilerstellungstrigger für App-Anomalien

Android 17 führt einen Dienst zur Anomalieerkennung auf dem Gerät ein, der ressourcenintensive Verhaltensweisen und potenzielle Kompatibilitätsregressionen überwacht. Dieser Dienst ist in ProfilingManager eingebunden und ermöglicht es Ihrer Anwendung, Profilerstellungsartefakte zu empfangen, die durch bestimmte vom System erkannte Ereignisse ausgelöst werden.

Verwenden Sie den Trigger TRIGGER_TYPE_ANOMALY, um Leistungsprobleme des Systems zu erkennen, z. B. übermäßige Binder-Aufrufe und übermäßige Arbeitsspeichernutzung. Wenn eine App die vom Betriebssystem definierten Arbeitsspeicherlimits überschreitet, können Entwickler über den Anomalie-Trigger App-spezifische Heap-Dumps erhalten, um Arbeitsspeicherprobleme zu identifizieren und zu beheben. Außerdem stellt der Anomalie-Trigger bei übermäßigem Binder-Spam ein Stack-Sampling-Profil für Binder-Transaktionen bereit.

Dieser API-Callback erfolgt vor allen vom System auferlegten Maßnahmen. Beispielsweise können Entwickler damit Debug-Daten erfassen, bevor die App vom System beendet wird, weil sie die Speicherlimits überschreitet.

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 APIs

Mit Android 17 werden neue JobDebugInfo-APIs eingeführt, mit denen Entwickler ihre JobScheduler-Jobs debuggen können. Sie können damit herausfinden, warum sie nicht ausgeführt werden, wie lange sie ausgeführt wurden, und andere zusammengefasste Informationen abrufen.

Die erste Methode der erweiterten JobDebugInfo APIs ist getPendingJobReasonStats(). Sie gibt eine Zuordnung der Gründe, warum der Job im Status „Ausführung ausstehend“ war, und die jeweiligen kumulativen ausstehenden Dauern zurück. Diese Methode kombiniert die Methoden getPendingJobReasonsHistory() und getPendingJobReasons(), um Ihnen Einblick zu geben, warum ein geplanter Job nicht wie erwartet ausgeführt wird. Sie vereinfacht jedoch den Informationsabruf, da sowohl die Dauer als auch der Jobgrund in einer einzigen Methode verfügbar sind.

Für eine bestimmte jobId kann die Methode beispielsweise PENDING_JOB_REASON_CONSTRAINT_CHARGING und eine Dauer von 60.000 ms zurückgeben. Das bedeutet, dass der Job 60.000 ms lang ausstehend war, weil die Einschränkung für das Laden nicht erfüllt wurde.

Wake-Locks mit Listener-Unterstützung für Alarme reduzieren, die im Ruhemodus zulässig sind

Android 17 führt eine neue Variante von AlarmManager.setExactAndAllowWhileIdle ein, die anstelle eines PendingIntent ein OnAlarmListener akzeptiert. Dieser neue Callback-basierte Mechanismus ist ideal für Apps, die derzeit auf kontinuierliche Wakelocks angewiesen sind, um regelmäßige Aufgaben auszuführen, z. B. Messaging-Apps, die Socket-Verbindungen aufrechterhalten.

Datenschutz

Android 17 enthält die folgenden neuen Funktionen, um den Datenschutz für Nutzer zu verbessern.

Plattformunterstützung für Encrypted Client Hello (ECH)

Mit Android 17 wird die Plattformunterstützung für Encrypted Client Hello (ECH) eingeführt, eine erhebliche Verbesserung des Datenschutzes für die Netzwerkkommunikation. ECH ist eine TLS 1.3-Erweiterung, die den Server Name Indication (SNI) während des ersten TLS-Handshakes verschlüsselt. Diese Verschlüsselung trägt zum Schutz der Privatsphäre der Nutzer bei, da es für Netzwerkvermittler schwieriger wird, die spezifische Domain zu identifizieren, mit der eine App eine Verbindung herstellt.

Die Plattform enthält jetzt die erforderlichen APIs für Netzwerkbibliotheken, um ECH zu implementieren. Dazu gehören neue Funktionen in DnsResolver zum Abfragen von HTTPS-DNS-Einträgen mit ECH-Konfigurationen und neue Methoden in den SSLEngines und SSLSockets von Conscrypt, um ECH zu aktivieren, indem diese Konfigurationen beim Herstellen einer Verbindung zu einer Domain übergeben werden. Entwickler können ECH-Einstellungen konfigurieren, z. B. die optionale Aktivierung oder die obligatorische Verwendung, über das neue <domainEncryption> Element in der Konfigurationsdatei für die Netzwerksicherheit, die global oder pro Domain angewendet werden kann.

Es wird erwartet, dass beliebte Netzwerkbibliotheken wie HttpEngine, WebView und OkHttp diese Plattform-APIs in zukünftigen Updates integrieren, wodurch es für Apps einfacher wird, ECH zu übernehmen und den Datenschutz für Nutzer zu verbessern.

Weitere Informationen finden Sie in der Dokumentation zu Encrypted Client Hello.

Android-Kontaktauswahl

Die Android-Kontaktauswahl ist eine standardisierte, durchsuchbare Oberfläche, über die Nutzer Kontakte mit Ihrer App teilen können. Sie ist auf Geräten mit Android 17 (API-Level 37) oder höher verfügbar und bietet eine datenschutzfreundliche Alternative zur umfassenden Berechtigung READ_CONTACTS. Anstatt Zugriff auf das gesamte Adressbuch des Nutzers anzufordern, gibt Ihre App die benötigten Datenfelder an, z. B. Telefonnummern oder E-Mail-Adressen, und der Nutzer wählt bestimmte Kontakte aus, die er teilen möchte. Dadurch erhält Ihre App nur Lesezugriff auf die ausgewählten Daten. So ist eine detaillierte Kontrolle möglich und gleichzeitig wird eine einheitliche Nutzererfahrung mit integrierter Suche, Google Suche-Profilwechsel und Mehrfachauswahl geboten, ohne dass Sie die Benutzeroberfläche erstellen oder verwalten müssen.

Weitere Informationen finden Sie in der Dokumentation zur Kontaktauswahl.

Sicherheit

Android 17 bietet die folgenden neuen Funktionen, um die Geräte- und App-Sicherheit zu verbessern.

Erweiterter Sicherheitsmodus für Android (AAPM)

Der erweiterte Sicherheitsmodus für Android bietet Android-Nutzern eine Reihe leistungsstarker neuer Sicherheitsfunktionen. Er ist ein wichtiger Schritt, um Nutzer – insbesondere solche mit einem höheren Risiko – vor ausgeklügelten Angriffen zu schützen. AAPM ist als Opt-in-Funktion konzipiert und wird mit einer einzigen Konfigurationseinstellung aktiviert, die Nutzer jederzeit aktivieren können, um eine vordefinierte Reihe von Sicherheitsmaßnahmen anzuwenden.

Zu diesen Kernkonfigurationen gehören das Blockieren der App-Installation aus unbekannten Quellen (Sideloading), das Einschränken der USB-Datensignalisierung und das Erzwingen von Google Play Protect-Scans. Dadurch wird die Angriffsfläche des Geräts erheblich verringert. Entwickler können diese Funktion über die AdvancedProtectionManager API einbinden, um den Status des Modus zu erkennen. So können Anwendungen automatisch eine verstärkte Sicherheitskonfiguration annehmen oder risikoreiche Funktionen einschränken, wenn ein Nutzer sich dafür entschieden hat.

PQC-APK-Signatur

Android unterstützt jetzt ein hybrides APK-Signaturschema, um die Signaturidentität Ihrer App vor potenziellen Bedrohungen durch Angriffe mit Quantencomputern zu schützen. Mit dieser Funktion wird ein neues APK-Signaturschema eingeführt, mit dem Sie einen klassischen Signaturschlüssel (z. B. RSA oder EC) mit einem neuen Post-Quanten-Kryptografie-Algorithmus (PQC) (ML-DSA) verknüpfen können.

Dieser hybride Ansatz sorgt dafür, dass Ihre App vor zukünftigen Quantenangriffen geschützt ist, und gewährleistet gleichzeitig die vollständige Abwärtskompatibilität mit älteren Android-Versionen und Geräten, die auf die klassische Signaturprüfung angewiesen sind.

Auswirkungen auf Entwickler

  • Apps, die die Play App-Signatur verwenden:Wenn Sie die Play App-Signatur verwenden, können Sie warten, bis Google Play Ihnen die Möglichkeit bietet, eine Hybridsignatur mit einem von Google Play generierten PQC-Schlüssel zu aktualisieren. So ist Ihre App geschützt, ohne dass eine manuelle Schlüsselverwaltung erforderlich ist.
  • Apps mit selbstverwalteten Schlüsseln:Entwickler, die ihre eigenen Signaturschlüssel verwalten, können aktualisierte Android-Build-Tools wie apksigner verwenden, um zu einer hybriden Identität zu wechseln, die einen PQC-Schlüssel mit einem neuen klassischen Schlüssel kombiniert. Sie müssen einen neuen klassischen Schlüssel erstellen. Sie können den älteren nicht wiederverwenden.

Verbindung

Android 17 bietet die folgenden Funktionen, um die Konnektivität von Geräten und Apps zu verbessern.

Eingeschränkte Satellitennetzwerke

Implementiert Optimierungen, damit Apps auch in Satellitennetzwerken mit geringer Bandbreite effektiv funktionieren.

Nutzererfahrung und System-UI

Android 17 enthält die folgenden Änderungen zur Verbesserung der Nutzerfreundlichkeit.

Eigene Lautstärkeregelung für Assistenten

Mit Android 17 wird ein eigener Lautstärkeregler für Assistant-Apps eingeführt, der für die Wiedergabe mit USAGE_ASSISTANT verwendet wird. Durch diese Änderung wird die Audioausgabe von Assistant vom Standard-Medienstream entkoppelt, sodass Nutzer die Lautstärke beider Streams separat regeln können. So ist es beispielsweise möglich, die Medienwiedergabe stummzuschalten, während Assistant-Antworten weiterhin hörbar sind, und umgekehrt.

Assistent-Apps mit Zugriff auf den neuen Audiomodus MODE_ASSISTANT_CONVERSATION können die Konsistenz der Lautstärkeregelung weiter verbessern. Assistent-Apps können diesen Modus verwenden, um dem System einen Hinweis auf eine aktive Assistant-Sitzung zu geben. So kann der Assistant-Stream außerhalb der aktiven USAGE_ASSISTANT-Wiedergabe oder mit verbundenen Bluetooth-Peripheriegeräten gesteuert werden.

Handoff

Handoff ist eine neue Funktion und API, die mit Android 17 eingeführt wird. App-Entwickler können sie einbinden, um ihren Nutzern geräteübergreifende Kontinuität zu bieten. Nutzer können damit eine App-Aktivität auf einem Android-Gerät starten und auf ein anderes Android-Gerät übertragen. Handoff wird im Hintergrund des Geräts eines Nutzers ausgeführt und zeigt verfügbare Aktivitäten von anderen Geräten des Nutzers in der Nähe über verschiedene Einstiegspunkte wie den Launcher und die Taskleiste auf dem empfangenden Gerät an.

Apps können Handoff so konfigurieren, dass dieselbe native Android-App gestartet wird, wenn sie auf dem empfangenden Gerät installiert und verfügbar ist. In diesem App-zu-App-Ablauf wird der Nutzer per Deeplink zur vorgesehenen Aktivität weitergeleitet. Alternativ kann die Übergabe von der App an das Web als Fallback-Option angeboten oder direkt mit der URL-Übergabe implementiert werden.

Die Unterstützung für die Übergabe wird pro Aktivität implementiert. Wenn Sie die Übergabe aktivieren möchten, rufen Sie die Methode setHandoffEnabled() für die Aktivität auf. Möglicherweise müssen zusätzliche Daten mit der Übergabe übermittelt werden, damit die neu erstellte Aktivität auf dem Empfängergerät den entsprechenden Status wiederherstellen kann. Implementieren Sie den Callback onHandoffActivityDataRequested(), um ein HandoffActivityData-Objekt zurückzugeben, das Details dazu enthält, wie Handoff die Aktivität auf dem Empfängergerät verarbeiten und neu erstellen soll.

Live-Update – Semantic Color API

Mit Android 17 werden im Rahmen von Live Update die Semantic Coloring APIs eingeführt, die Farben mit universeller Bedeutung unterstützen.

Die folgenden Klassen unterstützen die semantische Farbgebung:

Ausmalen

  • Grün: Wird mit Sicherheit assoziiert. Diese Farbe sollte verwendet werden, um anderen mitzuteilen, dass du dich in Sicherheit befindest.
  • Orange: Zur Kennzeichnung von Vorsicht und physischen Gefahren. Diese Farbe sollte verwendet werden, wenn Nutzer darauf aufmerksam gemacht werden müssen, dass sie bessere Schutzeinstellungen festlegen sollten.
  • Rot: Steht im Allgemeinen für Gefahr oder Stopp. Sie sollte nur angezeigt werden, wenn die Aufmerksamkeit der Nutzer dringend erforderlich ist.
  • Blau: Neutrale Farbe für informative Inhalte, die sich von anderen Inhalten abheben sollen.

Das folgende Beispiel zeigt, wie semantische Stile auf Text in einer Benachrichtigung angewendet werden:

  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)

UWB-Downlink-TDoA API für Android 17

Mit der Downlink Time Difference of Arrival (DL-TDoA)-Entfernungsmessung kann ein Gerät seine Position relativ zu mehreren Ankern bestimmen, indem es die relativen Ankunftszeiten von Signalen misst.

Das folgende Snippet zeigt, wie Sie den Ranging Manager initialisieren, die Gerätefunktionen prüfen und eine DL-TDoA-Sitzung starten:

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

Out-of-Band-Konfigurationen (OOB)

Das folgende Snippet enthält ein Beispiel für DL-TDoA-OOB-Konfigurationsdaten für WLAN und 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
};

Wenn Sie eine OOB-Konfiguration nicht verwenden können, weil sie fehlt, oder wenn Sie Standardwerte ändern müssen, die nicht in der OOB-Konfiguration enthalten sind, können Sie Parameter mit DlTdoaRangingParams.Builder erstellen, wie im folgenden Snippet gezeigt. Sie können diese Parameter anstelle von DlTdoaRangingParams.createFromFiraConfigPacket() verwenden:

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