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

WLAN-RTT wurde mit 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 (Access Points, APs) 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 AP-Standortdaten als ResponderLocation-Objekte dargestellt werden, darunter Breiten-, Längengrad und Höhe. 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 Anfrage für die Entfernungsmessung sendet, muss den FTM-Standard 802.11-2016 oder den Standard 802.11az (nicht triggerbasierte Entfernungsmessung) implementieren.
  • Auf dem Gerät, von dem die Entfernungsanfrage gesendet wird, muss Android 9 (API-Level 28) oder höher ausgeführt werden. 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 im Manifest Ihrer App die folgenden Berechtigungen 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 den Übertragungs-Intent 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 Standortermittlung (RangingRequest) wird erstellt, indem eine Liste von ZPs oder Wi‑Fi Aware-Peers angegeben wird, für die eine Standortermittlung angefordert wird. 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 mit der Methode addAccessPoint() ein Zugangspunkt angegeben werden, 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.

In ähnlicher Weise kann mit einer Anfrage zur Bereichserkennung ein Wi-Fi Aware-Peer über dessen MAC-Adresse oder PeerHandle mit den Methoden addWifiAwarePeer(MacAddress peer) und addWifiAwarePeer(PeerHandle peer) hinzugefügt werden. 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 zu diesem Zeitpunkt keinen Bereiching-Vorgang ausführen kann. Dies kann beispielsweise der Fall sein, wenn WLAN deaktiviert ist, die Anwendung zu viele Bereichserkennungsvorgänge angefordert hat und gedrosselt wird oder wenn 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. Beachten Sie, dass der Abtastvorgang zwar abgeschlossen sein kann, jedes Ergebnis jedoch weiterhin auf einen Fehler bei dieser bestimmten Messung hinweisen kann.

Bereichsergebnisse interpretieren

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 ist dies 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 Bereichsergebnisse kann eine andere Reihenfolge haben als die Peers (Zugangspunkte), die in der Entfernungsanfrage angegeben wurden. Daher sollten Sie die MAC-Adresse zur Identifizierung des Peers verwenden 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 Ergebniswerte mit den entsprechenden get-Methoden 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 Bereichsmessung vor Ablauf der Mindestzeit angefordert wird, gibt die API das im Cache gespeicherte Ergebnis der Entfernungsbestimmung 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 eine neue Entfernungssitzung anfordern, da dies die Zeit für die Entfernungsmessung erhöht. Um die nicht Trigger-basierte Bereichserkennung gemäß 802.11az optimal zu nutzen, lösen Sie die nächste Entfernungsanfrage 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