WLAN-Standort: Entfernung mit RTT

Mit der WLAN-Standortfunktion der Wi‑Fi RTT (Round-Trip-Time) API können Sie die Entfernung zu RTT-fähigen WLAN-Zugangspunkten und Wi‑Fi Aware-Geräten in der Nähe messen.

Wenn Sie die Entfernung zu drei oder mehr Zugangspunkten messen, können Sie mit einem Trilateration-Algorithmus die Geräteposition schätzen, die am besten zu diesen Messungen passt. Das Ergebnis ist in der Regel auf 1–2 Meter genau.

Mit dieser Genauigkeit können Sie detaillierte standortbasierte Dienste entwickeln, z. B. Indoor-Navigation, eine eindeutige Sprachsteuerung (z. B. „Schalte diese Lampe ein“) und standortbasierte Informationen (z. B. „Gibt es Sonderangebote für dieses Produkt?“).

Das anfragende Gerät muss sich nicht mit den Zugangspunkten verbinden, um die Entfernung mithilfe von WLAN-RTT zu messen. Aus Datenschutzgründen kann nur das anfragende Gerät die Entfernung zum Zugangspunkt ermitteln. Die Zugangspunkte haben diese Informationen nicht. Wi‑Fi-RTT-Vorgänge sind für Apps im Vordergrund unbegrenzt, für Apps im Hintergrund jedoch gedrosselt.

Wi‑Fi-RTT und die zugehörigen FTM-Funktionen (Fine-Time-Measurement) sind im IEEE 802.11-2016-Standard spezifiziert. Für die Wi‑Fi-RTT ist die genaue Zeitmessung von FTM erforderlich, da die Entfernung zwischen zwei Geräten berechnet wird, indem die Zeit gemessen wird, die ein Paket für einen Hin- und Rückweg zwischen den Geräten benötigt, und diese Zeit mit der Lichtgeschwindigkeit multipliziert wird.

Mit Android 15 (API-Level 35) wurde die Unterstützung für die nicht triggerbasierte (NTB) Entfernungsmessung nach IEEE 802.11az eingeführt.

Implementierungsunterschiede je nach Android-Version

Wi‑Fi RTT wurde in Android 9 (API-Level 28) eingeführt. Wenn Sie dieses Protokoll verwenden, um den Standort eines Geräts mithilfe von Multilateration mit Geräten mit Android 9 zu ermitteln, benötigen Sie Zugriff auf vorab festgelegte Standortdaten von Zugangspunkten (AP) in Ihrer App. Sie entscheiden selbst, wie Sie diese Daten speichern und abrufen.

Auf Geräten mit Android 10 (API-Level 29) und höher können Standortdaten von Zugangspunkten als ResponderLocation-Objekte dargestellt werden, die geografische Breite, geografische Länge und Höhe enthalten. Bei WLAN-RTT-Zugangspunkten, die LCI-/LCR-Daten (Location Configuration Information/Location Civic Report) unterstützen, gibt das Protokoll während des Abstandsbestimmungsverfahrens ein ResponderLocation-Objekt zurück.

Mit dieser Funktion können Apps ZPs direkt nach ihrer Position fragen, anstatt diese Informationen vorab speichern zu müssen. So kann Ihre App ZPs finden und ihre Positionen bestimmen, auch wenn die ZPs vorher nicht bekannt waren, z. B. wenn ein Nutzer ein neues Gebäude betritt.

Die Unterstützung von IEEE 802.11az-NTB-Messungen ist auf Geräten mit Android 15 (API-Ebene 35) und höher verfügbar. Wenn das Gerät den IEEE 802.11az-NTB-Initiatormodus unterstützt (WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), kann Ihre App mit einer einzigen Reichweitesanfrage sowohl IEEE 802.11mc- als auch IEEE 802.11az-kompatible ZPs finden. Die RangingResult API wurde um Informationen zum Mindest- und Höchstwert erweitert, der für das Intervall zwischen den Messwerten verwendet werden kann. Das genaue Intervall wird von Ihrer App gesteuert.

Voraussetzungen

  • Die Hardware des Geräts, das die Abfrage sendet, muss den FTM-Standard 802.11-2016 oder den Standard 802.11az (nicht triggerbasiertes Abtasten) implementieren.
  • Auf dem Gerät, das die Anfrage sendet, muss Android 9 (API-Ebene 28) oder höher installiert sein. Die nicht triggerbasierte Entfernungsmessung nach IEEE 802.11az ist auf Geräten mit Android 15 (API-Level 35) und höher aktiviert.
  • Auf dem Gerät, das die Anfrage sendet, müssen die Standortdienste und die WLAN-Suche aktiviert sein (unter Einstellungen > Standort).
  • Wenn die App, die die Anfrage für die Standortermittlung sendet, auf Android 13 (API-Level 33) oder höher ausgerichtet ist, muss sie die Berechtigung NEARBY_WIFI_DEVICES haben. Wenn eine solche App auf eine frühere Android-Version ausgerichtet ist, muss sie stattdessen die Berechtigung ACCESS_FINE_LOCATION haben.
  • Die App muss den Bereich der Zugangspunkte abfragen, während die App sichtbar ist oder sich in einem Dienst im Vordergrund befindet. Die App kann nicht im Hintergrund auf Standortinformationen zugreifen.
  • Der Zugangspunkt muss den FTM-Standard IEEE 802.11-2016 oder den Standard IEEE 802.11az (nicht triggerbasiertes Ranging) implementieren.

Einrichten

So richten Sie Ihre App für die Verwendung von WLAN-RTT ein:

1. Berechtigungen anfordern

Fordern Sie die folgenden Berechtigungen im Manifest Ihrer App an:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- If your app targets Android 13 (API level 33)
     or higher, you must declare the NEARBY_WIFI_DEVICES permission. -->
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
                 <!-- If your app derives location information from Wi-Fi APIs,
                      don't include the "usesPermissionFlags" attribute. -->
                 android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
                 <!-- If any feature in your app relies on precise location
                      information, don't include the "maxSdkVersion"
                      attribute. -->
                 android:maxSdkVersion="32" />

Die Berechtigungen NEARBY_WIFI_DEVICES und ACCESS_FINE_LOCATION sind gefährliche Berechtigungen. Sie müssen sie also jedes Mal zur Laufzeit anfordern, wenn der Nutzer einen RTT-Scan ausführen möchte. Ihre App muss die Berechtigung des Nutzers anfordern, wenn diese nicht bereits erteilt wurde. Weitere Informationen zu Laufzeitberechtigungen finden Sie unter App-Berechtigungen anfordern.

2. Prüfen, ob das Gerät WLAN-RTT unterstützt

Mit der PackageManager API können Sie prüfen, ob das Gerät WLAN-RTT unterstützt:

Kotlin

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

Java

context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);

3. Prüfen, ob WLAN-RTT verfügbar ist

WLAN-RTT ist möglicherweise auf dem Gerät vorhanden, aber nicht verfügbar, weil der Nutzer WLAN deaktiviert hat. Je nach Hardware- und Firmwarefunktionen unterstützen einige Geräte möglicherweise keine WLAN-RTT-Funktion, wenn SoftAP oder Tethering verwendet werden. Wenn Sie prüfen möchten, ob WLAN-RTT verfügbar ist, rufen Sie isAvailable() auf.

Die Verfügbarkeit von WLAN-RTT kann sich jederzeit ändern. Ihre App sollte einen BroadcastReceiver registrieren, um ACTION_WIFI_RTT_STATE_CHANGED zu empfangen, das gesendet wird, wenn sich die Verfügbarkeit ändert. Wenn Ihre App die Broadcastabsicht empfängt, sollte sie den aktuellen Verfügbarkeitsstatus prüfen und ihr Verhalten entsprechend anpassen.

Beispiel:

Kotlin

val filter = IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED)
val myReceiver = object: BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (wifiRttManager.isAvailable) {
            
        } else {
            
        }
    }
}
context.registerReceiver(myReceiver, filter)

Java

IntentFilter filter =
    new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED);
BroadcastReceiver myReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (wifiRttManager.isAvailable()) {
            
        } else {
            
        }
    }
};
context.registerReceiver(myReceiver, filter);

Weitere Informationen finden Sie unter Übertragungen.

Abfrage erstellen

Eine Anfrage für die Entfernungsmessung (RangingRequest) wird erstellt, indem eine Liste von ZPs oder Wi‑Fi Aware-Peers angegeben wird, für die eine Entfernung gemessen werden soll. In einer einzigen Anfrage zur Entfernungsmessung können mehrere Zugangspunkte oder Wi‑Fi Aware-Peers angegeben werden. Die Entfernungen zu allen Geräten werden gemessen und zurückgegeben.

In einer Anfrage kann beispielsweise die Methode addAccessPoint() verwendet werden, um einen Zugangspunkt anzugeben, zu dem die Entfernung gemessen werden soll:

Kotlin

val req: RangingRequest = RangingRequest.Builder().run {
    addAccessPoint(ap1ScanResult)
    addAccessPoint(ap2ScanResult)
    build()
}

Java

RangingRequest.Builder builder = new RangingRequest.Builder();
builder.addAccessPoint(ap1ScanResult);
builder.addAccessPoint(ap2ScanResult);

RangingRequest req = builder.build();

Ein Zugangspunkt wird durch sein ScanResult-Objekt identifiziert, das durch Aufrufen von WifiManager.getScanResults() abgerufen werden kann. Mit addAccessPoints(List<ScanResult>) können Sie mehrere Zugangspunkte gleichzeitig hinzufügen.

ScanResult-Objekte können sowohl von IEEE 802.11mc (is80211mcResponder()) als auch von IEEE 802.11az (is80211azNtbResponder()) unterstützte ZPs mit nicht triggerbasierter Entfernungsmessung enthalten. Geräte, die IEEE 802.11az-NTB-Messungen unterstützen, führen je nach den Fähigkeiten des ZP entweder 802.11mc- oder 802.11az-Messungen durch. Standardmäßig wird 802.11az verwendet, wenn der ZP beide unterstützt. Geräte, die IEEE 802.11az nicht unterstützen, führen alle Abfragen mit dem IEEE 802.11mc-Protokoll durch.

Ebenso kann bei einer Abfrage ein Wi‑Fi Aware-Peer entweder über seine MAC-Adresse oder seine PeerHandle hinzugefügt werden, und zwar mit den Methoden addWifiAwarePeer(MacAddress peer) und addWifiAwarePeer(PeerHandle peer). Weitere Informationen zum Auffinden von Wi‑Fi Aware-Peers finden Sie in der Wi‑Fi Aware-Dokumentation.

Abfragebereich

Eine App sendet eine Abfrage mit der Methode WifiRttManager.startRanging() und gibt Folgendes an: RangingRequest, um den Vorgang anzugeben, Executor, um den Callback-Kontext anzugeben, und RangingResultCallback, um die Ergebnisse zu empfangen.

Beispiel:

Kotlin

val mgr = context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE) as WifiRttManager
val request: RangingRequest = myRequest
mgr.startRanging(request, executor, object : RangingResultCallback() {

    override fun onRangingResults(results: List<RangingResult>) {  }

    override fun onRangingFailure(code: Int) {  }
})

Java

WifiRttManager mgr =
      (WifiRttManager) Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);

RangingRequest request ...;
mgr.startRanging(request, executor, new RangingResultCallback() {

  @Override
  public void onRangingFailure(int code) {  }

  @Override
  public void onRangingResults(List<RangingResult> results) {  }
});

Der Abtastvorgang wird asynchron ausgeführt und die Ergebnisse werden in einem der Callbacks von RangingResultCallback zurückgegeben:

  • Wenn der gesamte Abtastvorgang fehlschlägt, wird der Rückruf onRangingFailure mit einem Statuscode ausgelöst, der in RangingResultCallback beschrieben ist. Ein solcher Fehler kann auftreten, wenn der Dienst derzeit keinen Abstandsmessungsvorgang ausführen kann, z. B. weil das WLAN deaktiviert ist, weil die Anwendung zu viele Abstandsmessungsvorgänge angefordert hat und gedrosselt wird oder weil ein Berechtigungsproblem vorliegt.
  • Wenn der Abfragevorgang abgeschlossen ist, wird der Callback onRangingResults mit einer Liste von Ergebnissen ausgelöst, die der Liste der Anfragen entspricht – ein Ergebnis für jede Anfrage. Die Reihenfolge der Ergebnisse stimmt nicht unbedingt mit der Reihenfolge der Anfragen überein. Hinweis: Der Abtastvorgang kann abgeschlossen sein, aber jedes Ergebnis kann dennoch auf einen Fehler bei dieser bestimmten Messung hinweisen.

Ergebnisse der Reichweitenmessung auswerten

Jedes der vom onRangingResults-Callback zurückgegebenen Ergebnisse wird durch ein RangingResult-Objekt angegeben. Gehen Sie bei jeder Anfrage so vor:

1. Anfrage identifizieren

Identifizieren Sie die Anfrage anhand der Informationen, die beim Erstellen der RangingRequest angegeben wurden: meistens eine MAC-Adresse im ScanResult, die einen Zugangspunkt identifiziert. Die MAC-Adresse kann mit der Methode getMacAddress() aus dem Ergebnis der Entfernungsmessung abgerufen werden.

Die Liste der Ergebnisse der Standortbestimmung kann sich von der Reihenfolge der in der Standortbestimmungsanfrage angegebenen Peers (Zugangspunkte) unterscheiden. Verwenden Sie daher die MAC-Adresse, um den Peer zu identifizieren, und nicht die Reihenfolge der Ergebnisse.

2. Prüfen, ob jede Messung erfolgreich war

Verwenden Sie die Methode getStatus(), um festzustellen, ob eine Messung erfolgreich war. Jeder andere Wert als STATUS_SUCCESS weist auf einen Fehler hin. Ein Fehler bedeutet, dass alle anderen Felder dieses Ergebnisses (mit Ausnahme der Anfrage-ID oben) ungültig sind und die entsprechende get*-Methode mit einer IllegalStateException-Ausnahme fehlschlägt.

3. Ergebnisse für jede erfolgreiche Messung abrufen

Für jede erfolgreiche Messung (RangingResult) können Sie mit den entsprechenden get-Methoden Ergebniswerte abrufen:

  • Entfernung in mm und Standardabweichung der Messung:

    getDistanceMm()

    getDistanceStdDevMm()

  • RSSI der für die Messungen verwendeten Pakete:

    getRssi()

  • Die Zeit in Millisekunden, zu der die Messung durchgeführt wurde (Zeit seit dem Start):

    getRangingTimestampMillis()

  • Anzahl der versuchten und der erfolgreichen Messungen, auf denen die Entfernungsmessungen basieren:

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • Mindest- und Höchstzeit, die ein Clientgerät zwischen zwei 11az-NTB-Messungen warten muss:

    getMinTimeBetweenNtbMeasurementsMicros() und getMaxTimeBetweenNtbMeasurementsMicros() geben die minimale und maximale Zeit zurück. Wenn die nächste Abstandsmessung angefordert wird, bevor die Mindestzeit abgelaufen ist, gibt die API das im Cache gespeicherte Abstandsergebnis zurück. Wenn die nächste Entfernungsmessung nach Ablauf der maximalen Zeit angefordert wird, beendet die API die Entfernungsmessung ohne Trigger und verhandelt eine neue Entfernungsmessung mit der antwortenden Station. Sie sollten keine neue Abstandsmessung anfordern, da dies die Messzeit verlängert. Wenn Sie die Effizienz der nicht triggerbasierten 802.11az-Messung voll ausschöpfen möchten, lösen Sie die nächste Anfrage für die Entfernungsmessung zwischen der minimalen und maximalen Messzeit aus, die in der vorherigen RangingResult-Messung angegeben wurde.

  • Wiederholungen des Long Training Field (LTF), die von Responder- und Initiatorstationen in der Präambel für das IEEE 802.11az-NTB verwendet werden, führen zu:

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • Anzahl der gesendeten und empfangenen räumlichen Zeitstreams (STS), die die Initiatorstation für das IEEE 802.11az-NTB-Ergebnis verwendet hat:

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Android-Geräte, die WiFi-RTT unterstützen

In den folgenden Tabellen sind einige Smartphones, Zugangspunkte und Geräte für Einzelhandel, Lagerhäuser und Vertriebszentren aufgeführt, die WiFi-RTT unterstützen. Diese sind bei weitem nicht vollständig. Wir empfehlen Ihnen, sich an uns zu wenden, um Ihre RTT-kompatiblen Produkte hier aufzunehmen.

Zugangspunkte

Hersteller und Modell Supportdatum
Nest Wifi Pro (Wi‑Fi 6E) Unterstützt
Compulab WILD AP Unterstützt
Google Wifi Unterstützt
Google Nest Wifi-Router Unterstützt
Google Nest Wifi-Zugangspunkt Unterstützt
Aruba AP-635 Unterstützt
Cisco 9130 Unterstützt
Cisco 9136 Unterstützt
Cisco 9166 Unterstützt
Cisco 9164 Unterstützt
Aruba AP-505 Unterstützt
Aruba AP-515 Unterstützt
Aruba AP-575 Unterstützt
Aruba AP-518 Unterstützt
Aruba AP-505H Unterstützt
Aruba AP-565 Unterstützt
Aruba AP-535 Unterstützt

Smartphones

Hersteller und Modell Android-Version
Pixel 6 9.0+
Pixel 6 Pro 9.0+
Pixel 5 9.0+
Pixel 5a 9.0+
Pixel 5a (5G) 9.0+
Xiaomi Mi 10 Pro 9.0+
Xiaomi Mi 10 9.0+
Xiaomi Redmi Mi 9T Pro 9.0+
Xiaomi Mi 9T 9.0+
Xiaomi Mi 9 9.0+
Xiaomi Mi Note 10 9.0+
Xiaomi Mi Note 10 Lite 9.0+
Xiaomi Redmi Note 9S 9.0+
Xiaomi Redmi Note 9 Pro 9.0+
Xiaomi Redmi Note 8T 9.0+
Xiaomi Redmi Note 8 9.0+
Xiaomi Redmi K30 Pro 9.0+
Xiaomi Redmi K20 Pro 9.0+
Xiaomi Redmi K20 9.0+
Xiaomi Redmi Note 5 Pro 9.0+
Xiaomi Mi CC9 Pro 9.0+
LG G8X ThinQ 9.0+
LG V50S ThinQ 9.0+
LG V60 ThinQ 9.0+
LG V30 9.0+
Samsung Galaxy Note 10+ 5G 9.0+
Samsung Galaxy S20+ 5G 9.0+
Samsung Galaxy S20+ 9.0+
Samsung Galaxy S20 5G 9.0+
Samsung Galaxy S20 Ultra 5G 9.0+
Samsung Galaxy S20 9.0+
Samsung Galaxy Note 10+ 9.0+
Samsung Galaxy Note 10 5G 9.0+
Samsung Galaxy Note 10 9.0+
Samsung A9 Pro 9.0+
Google Pixel 4 XL 9.0+
Google Pixel 4 9.0+
Google Pixel 4a 9.0+
Google Pixel 3 XL 9.0+
Google Pixel 3 9.0+
Google Pixel 3a XL 9.0+
Google Pixel 3a 9.0+
Google Pixel 2 XL 9.0+
Google Pixel 2 9.0+
Google Pixel 1 XL 9.0+
Google Pixel 1 9.0+
Poco X2 9.0+
Sharp Aquos R3 SH-04L 9.0+

Geräte für Einzelhandel, Lagerhäuser und Vertriebszentren

Hersteller und Modell Android-Version
Zebra PS20 10.0 und höher
Zebra TC52/TC52HC 10.0 und höher
Zebra TC57 10.0 und höher
Zebra TC72 10.0 und höher
Zebra TC77 10.0 und höher
Zebra MC93 10.0 und höher
Zebra TC8300 10.0 und höher
Zebra VC8300 10.0 und höher
Zebra EC30 10.0 und höher
Zebra ET51 10.0 und höher
Zebra ET56 10.0 und höher
Zebra L10 10.0 und höher
Zebra CC600/CC6000 10.0 und höher
Zebra MC3300x 10.0 und höher
Zebra MC330x 10.0 und höher
Zebra TC52x 10.0 und höher
Zebra TC57x 10.0 und höher
Zebra EC50 (LAN und HC) 10.0 und höher
Zebra EC55 (WAN) 10.0 und höher
Zebra WT6300 10.0 und höher
Skorpio X5 10.0 und höher