Reichweite zwischen Geräten

Mit Android 16 wird das Ranging-Modul eingeführt, das eine einheitliche und standardisierte Schnittstelle für die genaue Entfernungsmessung zwischen Geräten bietet. Mit dieser API können Sie die Entfernung und Position von Peer-Geräten messen, ohne jede Ranging-Technologie einzeln verarbeiten zu müssen.

Das Ranging-Modul unterstützt die folgenden Technologien:

Entfernungsmessung – Funktionen und Verfügbarkeit

Die Klasse RangingManager stellt Apps Informationen zu den vom lokalen Gerät unterstützten Technologien zur Entfernungsmessung sowie zur Verfügbarkeit und den Funktionen der einzelnen Technologien zur Verfügung. Apps können sich für ein Callback registrieren, um über Änderungen an der Verfügbarkeit oder den Funktionen unterstützter Technologien informiert zu werden.

Geräterollen

Ein Gerät, das an einer Distanzmessung teilnimmt, muss entweder ein Initiator oder ein Responder sein. Das Initiatorgerät startet die Distanzmessung mit einem oder mehreren Respondergeräten. Ein Responder-Gerät reagiert jeweils nur auf Ranging-Anfragen von einem Initiator. Mit der Klasse RangingPreference können Sie die Rolle für ein bestimmtes Gerät in einer Ranging-Sitzung angeben.

Sitzungstypen für die Reichweite

Wenn Sie eine Ranging-Sitzung zwischen Geräten starten, ist es oft erforderlich, einen Out-of-Band-Datentransport (OOB) einzurichten, um Parameter für die Sitzung auszutauschen.

Das Ranging-Modul kann OOB-Verhandlungen für Sie übernehmen, unterstützt aber auch benutzerdefinierte OOB-Implementierungen.

Abbildung 1. OOB-Ablauf für Sitzungstypen.

Standard-OOB-Implementierung

Bei diesem Sitzungstyp (RANGING_SESSION_OOB) übernimmt das Ranging-Modul die OOB-Verhandlungen zum Starten einer Ranging-Sitzung. Es werden geeignete Parameter basierend auf den von der App bereitgestellten Einstellungen für die Entfernungsmessung ausgewählt und die entsprechenden Technologien verwendet, je nachdem, was beide Geräte unterstützen. Für diesen Sitzungstyp wird ein standardisiertes OOB specification verwendet.

Das Ranging-Modul definiert nur das OOB-Datenformat und die Sequenz, die für die Interaktion mit einem Peer-Gerät verwendet werden sollen. Es kümmert sich nicht um die Erkennung von Peer-Geräten oder den Verbindungsaufbau.

Benutzerdefinierte OOB-Implementierung

Bei diesem Sitzungstyp (RANGING_SESSION_RAW) umgeht die App den OOB-Ablauf des Ranging-Moduls und verarbeitet ihre eigene OOB-Aushandlung und ihre eigenen Parameter. Das bedeutet, dass die App ermitteln muss, welche Technologien das Peer-Gerät unterstützt, die Reichweitenparameter aushandeln und die Reichweitensitzung starten muss.

Einstellungen für die Entfernungsmessung

Verwenden Sie ein RangingPreference-Objekt, um die ausgewählten Parameter für eine Ranging-Sitzung anzugeben. Das bedeutet:

  • Geräterolle: Gibt an, ob das Gerät der Initiator oder der Responder ist.
  • Konfiguration der Entfernungsmessung: Ein RangingConfig-Objekt gibt den Typ der Ranging-Sitzung und andere Parameter an, die zum Starten einer Ranging-Sitzung erforderlich sind.
  • Sitzungskonfiguration: Ein SessionConfig-Objekt gibt Parameter an, die für die Ranging-Sitzung erzwungen werden sollen, z. B. das Messlimit, die Sensorfusion und die Geofence-Konfiguration.

Berechtigung für die Entfernungsmessung

Für das Ranging-Modul ist eine neue einheitliche Berechtigung (android.permission.RANGING) erforderlich, um auf alle aktuellen und zukünftigen Ranging-Technologien zuzugreifen. Diese Berechtigung ist in der Liste NEARBY_DEVICES_PERMISSIONS enthalten.

<uses-permission android:name="android.permission.RANGING" />

Einschränkungen

Das Ranging-Modul kann die Reichweite aus verschiedenen Gründen einschränken, z. B. aus den folgenden:

  • Drittanbieter-Apps dürfen nur auf unterstützten Geräten die Hintergrundentfernungsmessung mit Ultrabreitband durchführen. Die Entfernungsmessung im Hintergrund mit anderen Technologien ist nicht zulässig.
  • Die Entfernungsmessung ist nicht zulässig, wenn die maximale Anzahl gleichzeitiger Entfernungsmessungen pro Gerät erreicht wurde.
  • Die Reichweitenbestimmung kann aufgrund von Bedenken hinsichtlich der Systemintegrität eingeschränkt sein, z. B. in Bezug auf Akku, Leistung oder Speicher.

Für das Ranging-Modul gelten außerdem die folgenden bekannten Einschränkungen:

  • Das Ranging-Modul unterstützt nur die Übermittlung von Ranging-Daten an Peer-Geräte über Ultrabreitband. Bei anderen Technologien liefert das Ranging-Modul nur Entfernungsdaten an das Initiatorgerät.
  • Das Ranging-Modul unterstützt das dynamische Hinzufügen von Geräten nur im Rohbereichsmodus und nur für Ultrabreitband.
  • Das Ranging-Modul unterstützt keine 1:n-Ultra-Wideband-Sitzungen für Standard-OOB-Implementierungen. Wenn Sie mehrere Geräte-Handles übergeben, erstellt das Modul für jedes Peer-Gerät, das Ultrabreitband unterstützt, eine 1:1-Sitzung.

Reichweitenanalyse durchführen

So führen Sie eine Ranging-Sitzung mit dem Ranging-Modul durch:

  1. Prüfen Sie, ob auf allen Geräten Android 16 oder höher ausgeführt wird.
  2. Fordern Sie die android.permission.RANGING-Berechtigung im App-Manifest an.
  3. Bewerten Sie die Fähigkeiten und Verfügbarkeit von Technologien zur Entfernungsmessung.
  4. Ein Peer-Gerät für die Entfernungsmessung finden.
  5. Stellen Sie eine Verbindung für einen Out-of-Band-Austausch her. Verwenden Sie dazu einen der in Ranging-Sitzungstypen beschriebenen Sitzungstypen.
  6. Entfernungsmessung starten und kontinuierlich Entfernungsmessungsdaten erfassen
  7. Beenden Sie die Ranging-Sitzung.

Das folgende Codebeispiel veranschaulicht diese Schritte sowohl für die Initiator- als auch für die Responder-Rolle.

Kotlin

class RangingApp {

    // Starts a ranging session on the initiator side.
    fun startRangingInitiator(
        context: Context,
        deviceHandle: DeviceHandle,
        executor: Executor,
        callback: RangingSessionCallback
    ) {

        // Get the RangingManager which is the entry point for ranging module.
        val manager = context.getSystemService(RangingManager::class.java)

        // Create a new RangingSession using the provided executor and callback.
        val session = manager.createRangingSession(executor, callback)

        // Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
        // the initiator role.
        val config = OobInitiatorRangingConfig.Builder()
            .setFastestRangingInterval(Duration.ofMillis(100))
            .setSlowestRangingInterval(Duration.ofMillis(5000))
            .setRangingMode(RANGING_MODE_AUTO)
            .setSecurityLevel(SECURITY_LEVEL_BASIC)
            .addDeviceHandle(deviceHandle)
            .build()

        // Create a RangingPreference, which specifies the role (initiator) and
        // configuration for the ranging session.
        val preference =
            RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build()

        // Start ranging session.
        session.start(preference)

        // If successful, the ranging data will be sent through callback#onResults

        // Stop ranging session
        session.stop()
    }

    // Starts a ranging session on the responder side.
    fun startRangingResponder(
        context: Context,
        deviceHandle: DeviceHandle,
        executor: Executor,
        callback: RangingSessionCallback
    ) {

        // Get the RangingManager which is the entry point for ranging module.
        val manager = context.getSystemService(RangingManager::class.java)

        // Create a new RangingSession using the provided executor and callback.
        val session = manager.createRangingSession(executor, callback)

        // Create an OobResponderRangingConfig, which specifies the ranging parameters for
        // the responder role.
        val config = OobResponderRangingConfig.Builder(deviceHandle).build()

        // Create a RangingPreference, which specifies the role (responder) and
        // configuration for the ranging session.
        val preference =
            RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build()

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

        // Stop the ranging session
        session.stop()
    }
}

Java

public class RangingApp {

    // Starts a ranging session on the initiator side.
    void startRangingInitiator(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {

        // Get the RangingManager which is the entry point for ranging module.
        RangingManager manager = context.getSystemService(RangingManager.class);

        // Create a new RangingSession using the provided executor and callback.
        RangingSession session = manager.createRangingSession(executor, callback);

        // Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
        // the initiator role.
        OobInitiatorRangingConfig config = new OobInitiatorRangingConfig.Builder()
                .setFastestRangingInterval(Duration.ofMillis(100))
                .setSlowestRangingInterval(Duration.ofMillis(5000))
                .setRangingMode(RANGING_MODE_AUTO)
                .setSecurityLevel(SECURITY_LEVEL_BASIC)
                .addDeviceHandle(deviceHandle)
                .build();

        // Create a RangingPreference, which specifies the role (initiator) and
        // configuration for the ranging session.
        RangingPreference preference =
                new RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build();

        // Start ranging session.
        session.start(preference);

        // If successful, the ranging data will be sent through callback#onResults

        // Stop ranging session
        session.stop();

    }

    // Starts a ranging session on the responder side.
    void startRangingResponder(Context context,  DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {

        // Get the RangingManager which is the entry point for ranging module.
        RangingManager manager = context.getSystemService(RangingManager.class);

        // Create a new RangingSession using the provided executor and callback.
        RangingSession session = manager.createRangingSession(executor, callback);

        // Create an OobResponderRangingConfig, which specifies the ranging parameters for
        // the responder role.
        OobResponderRangingConfig config = new OobResponderRangingConfig.Builder(  deviceHandle).build();

        // Create a RangingPreference, which specifies the role (responder) and
        // configuration for the ranging session.
        RangingPreference preference =
                new RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build();

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

        // Stop the ranging session
        session.stop();
    }
}

UWB-Interoperabilität mit iOS-Geräten

Das Ranging-Modul unterstützt die Interoperabilität mit iOS-Geräten über Ultrabreitband (UWB). Wenn Sie die Distanzmessung mit einem iOS-Gerät durchführen möchten, müssen Sie eine benutzerdefinierte OOB-Implementierung verwenden und die Distanzmessungssitzung mit bestimmten Parametern konfigurieren, die dem Apple Nearby Interaction Accessory Protocol entsprechen. Beispiel-App

Verwenden Sie beim Erstellen von RangingPreference die Parameter RawRangingDevice und UwbRangingParams, um die Konfiguration anzugeben. Die folgenden Parameter sind für die iOS-Interoperabilität entscheidend:

  • Konfigurations-ID:Verwenden Sie UwbRangingParams.CONFIG_UNICAST_DS_TWR.
  • Session Key Info:Geben Sie ein Byte-Array mit der Anbieter-ID und dem statischen STS-IV an.
  • Komplexer Kanal:Legen Sie die Kanalnummer und den Präambelindex entsprechend der Konfiguration des iOS-Geräts fest.

Das folgende Code-Snippet zeigt, wie Sie ein RangingPreference-Objekt für die Reichweitenermittlung eines Initiatorgeräts mit einem iOS-Responder erstellen:

Kotlin

// Create UwbRangingParams with iOS-specific configuration
val uwbRangingParams = UwbRangingParams.Builder(
    sessionId,
    UwbRangingParams.CONFIG_UNICAST_DS_TWR,
    sourceAddress,
    destinationAddress
)
    .setComplexChannel(
        UwbComplexChannel.Builder()
            .setChannel(channelNumber)
            .setPreambleIndex(preambleIndex)
            .build()
    )
    .setRangingUpdateRate(updateRate)
    .setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
    .setSlotDuration(slotDuration)
    .build()

// Create RawRangingDevice
val rawRangingDevice = RawRangingDevice.Builder()
    .setRangingDevice(RangingDevice.Builder().build())
    .setUwbRangingParams(uwbRangingParams)
    .build()

// Create SessionConfig
val sessionConfig = SessionConfig.Builder()
    .setAngleOfArrivalNeeded(true)
    .setDataNotificationConfig(DataNotificationConfig.Builder()
        .setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
        .build())
    .build()

// Create RangingPreference for the initiator
val preference = RangingPreference.Builder(
    RangingPreference.DEVICE_ROLE_INITIATOR,
    RawInitiatorRangingConfig.Builder()
        .addRawRangingDevice(rawRangingDevice)
        .build()
)
    .setSessionConfig(sessionConfig)
    .build()

Java

// Create UwbRangingParams with iOS-specific configuration
UwbRangingParams uwbRangingParams = new UwbRangingParams.Builder(
        sessionId,
        UwbRangingParams.CONFIG_UNICAST_DS_TWR,
        sourceAddress,
        destinationAddress)
        .setComplexChannel(new UwbComplexChannel.Builder()
                .setChannel(channelNumber)
                .setPreambleIndex(preambleIndex)
                .build())
        .setRangingUpdateRate(updateRate)
        .setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
        .setSlotDuration(slotDuration)
        .build();

// Create RawRangingDevice
RawRangingDevice rawRangingDevice = new RawRangingDevice.Builder()
        .setRangingDevice(new RangingDevice.Builder().build())
        .setUwbRangingParams(uwbRangingParams)
        .build();

// Create SessionConfig
SessionConfig sessionConfig = new SessionConfig.Builder()
        .setAngleOfArrivalNeeded(true)
        .setDataNotificationConfig(new DataNotificationConfig.Builder()
                .setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
                .build())
        .build();

// Create RangingPreference for the initiator
RangingPreference preference = new RangingPreference.Builder(
        RangingPreference.DEVICE_ROLE_INITIATOR,
        new RawInitiatorRangingConfig.Builder()
                .addRawRangingDevice(rawRangingDevice)
                .build())
        .setSessionConfig(sessionConfig)
        .build();

Beispiel-App

Ein End-to-End-Beispiel für die Verwendung des Ranging-Moduls finden Sie in der Beispiel-App in AOSP. Diese Beispiel-App deckt alle vom Ranging-Modul unterstützten Ranging-Technologien ab und umfasst Abläufe für beide unterstützten Sitzungstypen.

UWB-Interoperabilität mit iOS-Geräten

Die Android-Beispiel-App unterstützt das Starten einer UWB-Entfernungsmessung mit der iOS-Beispiel-App.

Abbildung 2. UWB-Nutzung unter Android und iOS.