Ultrabreitband-Kommunikation (UWB)

Ultrabreitband-Kommunikation ist eine Funktechnologie, die auf die präzise Entfernungsbestimmung zwischen Geräten ausgerichtet ist (Messung des Standorts mit einer Genauigkeit von 10 cm). Diese Funktechnologie kann eine geringe Energiedichte für Messungen auf kurze Distanz nutzen und eine Signalübertragung mit hoher Bandbreite über einen großen Teil des Funkspektrums durchführen. Die UWB-Bandbreite ist größer als 500 MHz (oder übersteigt 20% der anteiligen Bandbreite).

Controller/Initiator und gesteuertes Element/Responder

Die UWB-Kommunikation erfolgt zwischen zwei Geräten, wobei eines ein Controller und das andere ein gesteuertes Gerät ist. Der Controller bestimmt den komplexen Kanal (UwbComplexChannel), den die beiden Geräte gemeinsam nutzen, und ist der Initiator, während das gesteuerte Gerät der Responder ist.

Ein Controller kann mehrere steuerbare Elemente verarbeiten, ein steuerbares Element kann jedoch nur einem einzelnen Controller abonnieren. Sowohl Controller-/Initiator- als auch gesteuerte/antwortende Konfigurationen werden unterstützt.

Parameter für die Reichweite

Der Controller und das gesteuerte Gerät müssen sich gegenseitig identifizieren und die Abtastparameter kommunizieren, damit die Abtastung beginnen kann. Dieser Austausch wird von den Anwendungen mit einem sicheren Out-of-Band-Mechanismus (OOB) ihrer Wahl implementiert, z. B. Bluetooth Low Energy (BLE).

Zu den Abstandsparametern gehören unter anderem die lokale Adresse, der komplexe Kanal und der Sitzungsschlüssel. Beachten Sie, dass sich diese Parameter nach dem Ende der Standortermittlung ändern können und neu übertragen werden müssen, um die Standortermittlung fortzusetzen.

Hintergrunderfassung

Eine im Hintergrund ausgeführte App kann eine UWB-Messsitzung starten, wenn das Gerät dies unterstützt. Informationen zu den Funktionen Ihres Geräts finden Sie unter RangingCapabilities.

Die App erhält keine Berichte zur Positionsermittlung, wenn sie im Hintergrund ausgeführt wird. Sie erhält diese Berichte erst, wenn sie in den Vordergrund wechselt.

STS-Konfigurationen

Die App oder der Dienst stellt mithilfe einer verschlüsselten Zeitstempelsequenz (STS) einen Sitzungsschlüssel für jede Sitzung bereit. Ein bereitgestellter STS ist sicherer als eine statische STS-Konfiguration. Bereitstimmte STS werden auf allen UWB-fähigen Geräten mit Android 14 oder höher unterstützt.

Bedrohungskategorie Statische STS Bereitstimmte STS
Luft: Passiver Beobachter Mitigated (gemindert) Mitigated (gemindert)
Luft: Signalverstärkung Mitigated (gemindert) Mitigated (gemindert)
Luft: Replay-/Weiterleitungsangriff Anfällig Mitigated (gemindert)

Für bereitgestellte STS:

  1. Verwenden Sie die uwbConfigType in RangingParameters, die bereitgestellte STS unterstützt.

  2. Geben Sie den 16-Byte-Schlüssel in das Feld sessionKeyInfo ein.

Für statische STS:

  1. Verwenden Sie die uwbConfigType in RangingParameters, die statische STS unterstützt.

  2. Geben Sie den 8-Byte-Schlüssel in das Feld sessionKeyInfo ein.

Schritte

So verwenden Sie die UWB API:

  1. Prüfen Sie, ob auf den Android-Geräten Android 12 oder höher installiert ist und ob sie UWB mit PackageManager#hasSystemFeature("android.hardware.uwb") unterstützen.
  2. Wenn Sie die Reichweite mit IoT-Geräten ermitteln, müssen diese FiRa MAC 1.3-kompatibel sein.
  3. UWB-fähige Peer-Geräte mit einem OOB-Mechanismus Ihrer Wahl finden, z. B. BluetoothLeScanner
  4. Tauschen Sie die Abstandsmessungsparameter mit einem sicheren OOB-Mechanismus Ihrer Wahl aus, z. B. BluetoothGatt.
  5. Wenn der Nutzer die Sitzung beenden möchte, heben Sie den Gültigkeitsbereich der Sitzung auf.

Nutzungsbeschränkungen

Für die Nutzung der UWB API gelten die folgenden Einschränkungen:

  1. Die App, die neue UWB-Messsitzungen initiiert, muss eine App oder ein Dienst im Vordergrund sein, es sei denn, die Hintergrundmessung wird wie oben beschrieben unterstützt.
  2. Wenn die App während einer Sitzung in den Hintergrund verschoben wird, erhält sie möglicherweise keine Positionsberichte mehr. Die UWB-Sitzung wird jedoch in den unteren Schichten weiterhin aufrechterhalten. Wenn die App wieder in den Vordergrund wechselt, werden die Berichte zur Standortermittlung fortgesetzt.

Codebeispiele

Beispielanwendung

Ein End-to-End-Beispiel zur Verwendung der UWB Jetpack-Bibliothek finden Sie in unserer Beispielanwendung auf GitHub. In dieser Beispiel-App wird die UWB-Kompatibilität auf einem Android-Gerät geprüft, der Discovery-Prozess mit einem OOB-Mechanismus aktiviert und die UWB-Reichweite zwischen zwei UWB-fähigen Geräten eingerichtet. Das Beispiel deckt auch Anwendungsfälle für die Gerätesteuerung und die Medienfreigabe ab.

UWB-Messung

In diesem Codebeispiel wird die UWB-Messung für ein verwaltetes Gerät gestartet und beendet:

// The coroutineScope responsible for handling uwb ranging.
// This will be initialized when startRanging is called.
var job: Job?

// A code snippet that initiates uwb ranging for a Controlee.
suspend fun startRanging() {

    // Get the ranging parameter of a partnering Controller using an OOB mechanism of choice.
    val partnerAddress : Pair<UwbAddress, UwbComplexChannel> = listenForPartnersAddress()

    // Create the ranging parameters.
    val partnerParameters = RangingParameters(
        uwbConfigType = UwbRangingParameters.UWB_CONFIG_ID_1,
        // SessionKeyInfo is used to encrypt the ranging session.
        sessionKeyInfo = null,
        complexChannel = partnerAddress.second,
        peerDevices = listOf(UwbDevice.createForAddress(partnerAddress.first)),
        updateRateType = UwbRangingParameters.RANGING_UPDATE_RATE_AUTOMATIC
    )

    // Initiate a session that will be valid for a single ranging session.
    val clientSession = uwbManager.clientSessionScope()

    // Share the localAddress of the current session to the partner device.
    broadcastMyParameters(clientSession.localAddress)

    val sessionFlow = clientSession.prepareSession(partnerParameters)

    // Start a coroutine scope that initiates ranging.
    CoroutineScope(Dispatchers.Main.immediate).launch {
        sessionFlow.collect {
            when(it) {
                is RangingResultPosition -> doSomethingWithPosition(it.position)
                is RangingResultPeerDisconnected -> peerDisconnected(it)
            }
        }
    }
}

// A code snippet that cancels uwb ranging.
fun cancelRanging() {

    // Canceling the CoroutineScope will stop the ranging.
    job?.let {
        it.cancel()
    }
}

RxJava3-Unterstützung

Rxjava3-Unterstützung ist jetzt verfügbar, um die Interoperabilität mit Java-Clients zu verbessern. Diese Bibliothek bietet eine Möglichkeit, Ergebnisse für die Reichweite als Observable- oder Flowable-Stream abzurufen und den UwbClientSessionScope als einzelnes Objekt abzurufen.

private final UwbManager uwbManager;

// Retrieve uwbManager.clientSessionScope as a Single object
Single<UwbClientSessionScope> clientSessionScopeSingle =
                UwbManagerRx.clientSessionScopeSingle(uwbManager);
UwbClientSessionScope uwbClientSessionScope = clientSessionScopeSingle.blockingGet();

// Retrieve uwbClientSessionScope.prepareSession Flow as an Observable object
Observable<RangingResult> rangingResultObservable =
                UwbClientSessionScopeRx.rangingResultsObservable(clientSessionScope,
                        rangingParameters);

// Consume ranging results from Observable
rangingResultObservable.subscribe(
   rangingResult -> doSomethingWithRangingResult(result), // onNext
   (error) -> doSomethingWithError(error), // onError
   () -> doSomethingOnResultEventsCompleted(), //onCompleted
);
// Unsubscribe
rangingResultObservable.unsubscribe();
   

// Retrieve uwbClientSessionScope.prepareSession Flow as a Flowable object
Flowable<RangingResult> rangingResultFlowable =
                UwbClientSessionScopeRx.rangingResultsFlowable(clientSessionScope,
                        rangingParameters);

// Consume ranging results from Flowable using Disposable
Disposable disposable = rangingResultFlowable
   .delay(1, TimeUnit.SECONDS)
   .subscribeWith(new DisposableSubscriber<RangingResult> () {
      @Override public void onStart() {
          request(1);
      }
      
      @Override public void onNext(RangingResult rangingResult) {
             doSomethingWithRangingResult(rangingResult);
             request(1);
      }


      @Override public void onError(Throwable t) {
             t.printStackTrace();
      }


         @Override public void onComplete() {
            doSomethingOnEventsCompleted();
         }
   });

// Stop subscription
disposable.dispose();

Systemunterstützung

Hier finden Sie eine Liste der unterstützten Geräte von Partnern und SDKs von Drittanbietern.

UWB-fähige Mobilgeräte

Seit Januar 2025 unterstützen diese Geräte die Android UWB Jetpack-Bibliothek:

Vendor Gerätemodell
Google Google Pixel Pro (6 Pro und höher), Fold, Tablet
Motorola Edge 50 Ultra
Samsung Galaxy Note 20, Galaxy Plus und Ultra (S21 und höher), Galaxy Z Fold (Fold2 und höher)

Hinweis: Die UWB-Abstandsmessung im Hintergrund wird auf allen Geräten unterstützt, mit folgenden Ausnahmen:

  • Google Pixel 6 Pro und Google Pixel 7 Pro
  • Samsung-Smartphones mit Android 13 oder niedriger
  • Chinesische Samsung-Smartphones mit Android 14 oder niedriger

Drittanbieter-SDKs

Seit April 2023 sind diese Partnerlösungen mit der aktuellen Jetpack-Bibliothek kompatibel.

Bekanntes Problem: Bytereihenfolge für MAC-Adresse und statische STS-Anbieter-ID-Felder umgekehrt

Unter Android 13 und niedriger wird die Bytereihenfolge für die folgenden Felder vom Android-UWB-Stack fälschlicherweise umgekehrt:

  • MAC-Adresse des Geräts
  • MAC-Zieladresse
  • Statische STS-Anbieter-ID

Die Umkehrung der Bytereihenfolge tritt auf, weil der Android-Stack diese Felder als Werte und nicht als Arrays behandelt. Wir arbeiten mit FiRa zusammen, um die UCI-Spezifikation (CR-1112) zu aktualisieren und ausdrücklich anzugeben, dass diese Felder als Arrays behandelt werden sollten.

Dieses Problem wird durch das GMS Core-Update in der 2320XXXX-Version behoben. Damit Ihre Implementierung ab diesem Zeitpunkt mit Android-Geräten kompatibel ist, müssen IoT-Anbieter sie ändern, um eine Umkehrung der Bytesortierung dieser Felder zu vermeiden.