WLAN-Standort: Entfernung mit RTT

Mit der WLAN-Standortfunktion der Wi-Fi RTT (Round-Trip-Time) API kannst du die Entfernung zu RTT-fähigen WLAN-Zugangspunkten und Wi-Fi Aware-Peer-Geräten in der Nähe messen.

Wenn du die Entfernung zu drei oder mehr Zugangspunkten misst, kannst du einen Multilaterationsalgorithmus verwenden, um die Geräteposition zu 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 standortbezogene Dienste entwickeln, z. B. Navigation in Innenräumen, eindeutige Sprachsteuerung (z. B. „Schalte dieses Licht ein“) und standortbezogene Informationen (z. B. „Gibt es Sonderangebote für dieses Produkt?“).

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

Wi-Fi RTT und die zugehörigen FTM-Funktionen (Fine-Time-Measurement) sind im Standard IEEE 802.11-2016 spezifiziert. Für Wi-Fi RTT ist die genaue Zeitmessung durch FTM erforderlich, da die Entfernung zwischen zwei Geräten berechnet wird, indem die Zeit gemessen wird, die ein Paket für die Übertragung 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 gemäß IEEE 802.11az eingeführt.

Unterschiede bei der Implementierung je nach Android-Version

Wi-Fi RTT wurde in Android 9 (API-Level 28) eingeführt. Wenn Sie dieses Protokoll verwenden, um die Position eines Geräts mithilfe von Multilateration mit Geräten mit Android 9 zu bestimmen, müssen Sie in Ihrer App Zugriff auf vordefinierte Standortdaten von Zugangspunkten (Access Points, APs) haben. Sie können selbst entscheiden, 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, die Breiten-, Längen- und Höhenangaben enthalten. Bei Wi-Fi RTT-APs, die LCI/LCR-Daten (Location Configuration Information/Location Civic Report) unterstützen, gibt das Protokoll während der Entfernungsmessung ein ResponderLocation-Objekt zurück.

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

Die Unterstützung für IEEE 802.11az-NTB-Entfernungsmessung ist auf Geräten mit Android 15 (API-Level 35) und höher verfügbar. Wenn das Gerät den IEEE 802.11az-NTB-Initiatormodus unterstützt (gekennzeichnet durch WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), kann Ihre App mit einer einzigen Entfernungsanfrage sowohl IEEE 802.11mc- als auch IEEE 802.11az-fähige APs finden. Die RangingResult API wurde erweitert, um Informationen zum Mindest- und Höchstwert für das Intervall zwischen Entfernungsmessungen bereitzustellen. Das genaue Intervall wird von Ihrer App gesteuert.

Voraussetzungen

  • Die Hardware des Geräts, das die Entfernungsanfrage stellt, muss den FTM-Standard 802.11-2016 oder den Standard 802.11az (nicht triggerbasierte Entfernungsmessung) implementieren.
  • Auf dem Gerät, das die Entfernungsanfrage stellt, muss Android 9 (API-Level 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 Entfernungsanfrage stellt, müssen die Standortdienste und die WLAN-Suche aktiviert sein (unter Einstellungen > Standort).
  • Wenn die App, die die Entfernungsanfrage stellt, 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 die Reichweite der Zugangspunkte abfragen, während sie sichtbar ist oder als Dienst im Vordergrund ausgeführt wird. 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 triggerbasierte Entfernungsmessung) implementieren.

Einrichtung

Führe die folgenden Schritte aus, um deine App für die Verwendung von Wi-Fi RTT einzurichten.

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 daher jedes Mal zur Laufzeit anfordern, wenn der Nutzer einen RTT-Scanvorgang ausführen möchte. Ihre App muss die Berechtigung des Nutzers anfordern, wenn diese noch nicht erteilt wurde. Weitere Informationen zu Laufzeitberechtigungen finden Sie unter App-Berechtigungen anfordern.

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

Mit der PackageManager API können Sie prüfen, ob das Gerät Wi-Fi 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 Wi-Fi RTT möglicherweise nicht, wenn SoftAP oder Tethering verwendet werden. Mit isAvailable() können Sie prüfen, ob WLAN-RTT verfügbar ist.

Die Verfügbarkeit von Wi-Fi RTT kann sich jederzeit ändern. Deine App sollte einen BroadcastReceiver registrieren, um ACTION_WIFI_RTT_STATE_CHANGED zu empfangen, der gesendet wird, wenn sich die Verfügbarkeit ändert. Wenn deine App den Broadcast-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 Broadcasts.

Ranging-Anfrage erstellen

Eine Entfernungsanfrage (RangingRequest) wird erstellt, indem eine Liste von APs oder Wi-Fi Aware-Peers angegeben wird, für die eine Entfernung angefordert wird. In einer einzelnen Entfernungsmessungsanfrage 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 Zugriffspunkte in einem Batch hinzufügen.

ScanResult-Objekte können sowohl APs enthalten, die IEEE 802.11mc (is80211mcResponder()) unterstützen, als auch APs, die IEEE 802.11az-Entfernungsmessung ohne Trigger (is80211azNtbResponder()) unterstützen. Geräte, die IEEE 802.11az-NTB-Entfernungsmessung unterstützen, führen je nach den Funktionen des AP entweder 802.11mc- oder 802.11az-Entfernungsmessung durch. Wenn der AP beide unterstützt, wird standardmäßig 802.11az verwendet. Geräte, die IEEE 802.11az nicht unterstützen, führen alle Entfernungsmessungen mit dem IEEE 802.11mc-Protokoll durch.

Ebenso kann eine Entfernungsanfrage einen Wi-Fi Aware-Peer entweder über seine MAC-Adresse oder seine PeerHandle hinzufügen, indem die Methoden addWifiAwarePeer(MacAddress peer) bzw. addWifiAwarePeer(PeerHandle peer) verwendet werden. Weitere Informationen zum Erkennen von Wi-Fi Aware-Peers finden Sie in der Wi-Fi Aware-Dokumentation.

Entfernungsmessung anfordern

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

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 Ranging-Vorgang wird asynchron ausgeführt und die Ranging-Ergebnisse werden in einem der Callbacks von RangingResultCallback zurückgegeben:

  • Wenn der gesamte Entfernungsmessungsvorgang fehlschlägt, wird der Callback onRangingFailure mit einem Statuscode ausgelöst, der in RangingResultCallback beschrieben ist. Ein solcher Fehler kann auftreten, wenn der Dienst zu diesem Zeitpunkt keinen Entfernungsmessvorgang ausführen kann, z. B. weil das WLAN deaktiviert ist, weil die Anwendung zu viele Entfernungsmessvorgänge angefordert hat und gedrosselt wird oder weil ein Berechtigungsproblem vorliegt.
  • Wenn der Entfernungsmessungsvorgang abgeschlossen ist, wird der Callback onRangingResults mit einer Liste von Ergebnissen ausgelöst, die der Liste der Anfragen entspricht – ein Ergebnis pro Anfrage. Die Reihenfolge der Ergebnisse entspricht nicht unbedingt der Reihenfolge der Anfragen. Beachte, dass der Entfernungsmessvorgang zwar abgeschlossen werden kann, aber jedes Ergebnis dennoch auf einen Fehler bei der jeweiligen Messung hinweisen kann.

Entfernungsmessungsergebnisse interpretieren

Jedes der vom Callback onRangingResults zurückgegebenen Ergebnisse wird durch ein RangingResult-Objekt angegeben. Führen Sie bei jeder Anfrage die folgenden Schritte aus.

1. Anfrage identifizieren

Identifizieren Sie die Anfrage anhand der Informationen, die beim Erstellen des RangingRequest angegeben wurden. Meistens ist dies eine MAC-Adresse, die im ScanResult angegeben ist und einen Zugriffspunkt identifiziert. Die MAC-Adresse kann mit der Methode getMacAddress() aus dem Entfernungsmessergebnis abgerufen werden.

Die Liste der Entfernungsmessungsergebnisse kann eine andere Reihenfolge haben als die in der Anfrage zur Entfernungsmessung angegebenen Peers (Zugangspunkte). Du solltest daher die MAC-Adresse verwenden, um den Peer zu identifizieren, und nicht die Reihenfolge der Ergebnisse.

2. Feststellen, ob die einzelnen Messungen erfolgreich waren

Mit der Methode getStatus() können Sie feststellen, 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 oben genannten Anfrageidentifikation) ungültig sind und die entsprechende get*-Methode mit einer IllegalStateException-Ausnahme fehlschlägt.

3. Ergebnisse für jede erfolgreiche Messung erhalten

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

  • Entfernung in mm und die Standardabweichung der Messung:

    getDistanceMm()

    getDistanceStdDevMm()

  • RSSI der für die Messungen verwendeten Pakete:

    getRssi()

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

    getRangingTimestampMillis()

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

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

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

    getMinTimeBetweenNtbMeasurementsMicros() und getMaxTimeBetweenNtbMeasurementsMicros() geben die minimale und maximale Zeit zurück. Wenn die nächste Entfernungsmessung vor Ablauf der Mindestzeit angefordert wird, gibt die API das im Cache gespeicherte Entfernungsergebnis zurück. Wenn die nächste Entfernungsmessung nach Ablauf der maximalen Zeit angefordert wird, beendet die API die nicht auslösende Entfernungsmessung und handelt eine neue Entfernungsmessung mit der antwortenden Station aus. Du solltest es vermeiden, eine neue Entfernungsmessungssitzung anzufordern, da dies die Zeit für die Entfernungsmessung verlängert. Wenn du die Effizienz der nicht triggerbasierten Entfernungsmessung nach 802.11az voll ausschöpfen möchtest, solltest du die nächste Anfrage zur Entfernungsmessung zwischen der minimalen und maximalen Messzeit auslösen, die in der vorherigen RangingResult-Messung angegeben wurde.

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

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

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

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Android-Geräte, die Wi-Fi RTT unterstützen

In den folgenden Tabellen sind einige Smartphones, Zugangspunkte und Geräte für Einzelhandel, Lager und Vertriebszentren aufgeführt, die Wi-Fi RTT unterstützen. Diese Liste ist keineswegs vollständig. Wenden Sie sich an uns, um Ihre RTT-fähigen Produkte hier aufzulisten.

Zugangspunkte

Hersteller und Modell Supportdatum Protokoll
Google Nest Wifi Pro (Wi-Fi 6E) Unterstützt mc
Compulab WILD AP Unterstützt mc
Google Wifi Unterstützt mc
Google Nest WLAN-Router Unterstützt mc
Google Nest Wifi-Zugangspunkt Unterstützt mc
Aruba AP-635 Unterstützt mc
Cisco 9130 Unterstützt mc
Cisco 9136 Unterstützt mc
Cisco 9166 Unterstützt mc
Cisco 9164 Unterstützt mc
Cisco CW9172I Unterstützt mc/az
Cisco CW9172H Unterstützt mc/az
Cisco CW9176I Unterstützt mc/az
Cisco CW9178I Unterstützt mc/az
Aruba AP-505 Unterstützt mc
Aruba AP-515 Unterstützt mc
Aruba AP-575 Unterstützt mc
Aruba AP-518 Unterstützt mc
Aruba AP-505H Unterstützt mc
Aruba AP-565 Unterstützt mc
Aruba AP-535 Unterstützt mc
Aruba AP567 Unterstützt mc
Aruba AP577 Unterstützt mc
Aruba AP555 Unterstützt mc
Aruba AP635 Unterstützt mc
Aruba AP655 Unterstützt mc
Aruba AP615 Unterstützt mc
Aruba AP734 Unterstützt mc/az
Aruba AP735 Unterstützt mc/az
Aruba AP754 Unterstützt mc/az
Aruba AP755 Unterstützt mc/az

Smartphones

Hersteller und Modell Android-Version
Google Pixel 9 Pro XL 14+
Google Pixel 9 14+
Google Pixel 9 Pro 14+
Google Pixel 9 Pro XL 14+
Google Pixel 7a 14+
Google Pixel 7 14+
Google Pixel 8 14+
Google Pixel 8 Pro 14+
Google Pixel 8a 14+
Samsung SM-S918B 14+
Samsung SM-A515F 14+
Google Pixel 9 Pro 14+
Samsung SM-A546E 14+
Samsung SM-S928B 14+
Samsung SM-A217F 14+
Samsung SM-A715F 14+
Samsung SM-A528B 14+
Samsung SM-A135F 14+
Samsung SM-S911B 14+
Xiaomi 21091116AI 14+
Google Pixel 9 14+
Samsung SM-A127F 14+
Google Pixel 7 Pro 14+
Samsung SM-A556E 14+
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, Lager und Vertriebszentren

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