WLAN-Standort: Entfernung mit RTT

Sie können die WLAN-Standortfunktion der Wi-Fi RTT (Round-Trip-Time) API verwenden, um die Entfernung zu nahe gelegenen RTT-fähigen WLAN-Zugangspunkten und Peer-Wi-Fi Aware-Geräten zu messen.

Wenn Sie die Entfernung zu drei oder mehr Zugangspunkten messen, können Sie mithilfe eines Multilaterationsalgorithmus die Geräteposition schätzen, die am besten zu diesen Messungen passt. Die Genauigkeit des Ergebnisses beträgt in der Regel 1 bis 2 Meter.

Mit dieser Genauigkeit können Sie detaillierte standortbezogene Dienste entwickeln, z. B. die Navigation in Innenräumen, die eindeutige Sprachsteuerung (z. B. „Schalte dieses Licht ein“) und standortbasierte Informationen (z. B. „Gibt es Sonderangebote für dieses Produkt?“).

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

Wi-Fi-RTT und die zugehörigen Funktionen der Fine-Time-Measurement (FTM) sind im IEEE 802.11-2016-Standard angegeben. WLAN-RTT erfordert die genaue Zeitmessung von FTM, da sie die Entfernung zwischen zwei Geräten berechnet. Dazu wird die Zeit gemessen, die ein Paket für einen Umlauf zwischen den Geräten benötigt, und diese Zeit mit der Lichtgeschwindigkeit multipliziert.

Unterschiede bei der Implementierung je nach Android-Version

WLAN-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, benötigen Sie Zugriff auf vordefinierte Zugangspunkt-Standortdaten in Ihrer App. Sie müssen entscheiden, wie diese Daten gespeichert und abgerufen werden.

Auf Geräten mit Android 10 (API-Level 29) und höher können AP-Standortdaten als ResponderLocation-Objekte dargestellt werden. Dazu gehören unter anderem Breiten-, Längengrad und Höhe. Bei WLAN-RTT-APs, die Location Configuration Information/Location Civic Report (LCI/LCR-Daten) unterstützen, gibt das Protokoll während des Entfernungsprozesses ein ResponderLocation-Objekt zurück.

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

Voraussetzungen

  • Die Hardware des Geräts, von dem die Entfernungsanfrage gesendet wird, muss den FTM-Standard 802.11-2016 implementieren.
  • Auf dem Gerät, das die Entfernungsanfrage sendet, muss Android 9 (API-Level 28) oder höher installiert sein.
  • Auf dem Gerät, das die Entfernungsanfrage sendet, müssen unter Einstellungen > Standort die Standortdienste und die WLAN-Suche aktiviert sein.
  • Wenn die App, die die Entfernungsanfrage 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 ältere Android-Version ausgerichtet ist, muss sie stattdessen die Berechtigung ACCESS_FINE_LOCATION haben.
  • Die App muss den Bereich der Zugangspunkte abfragen, während sie sichtbar ist oder sich in einem Dienst im Vordergrund befindet. Die App kann nicht auf Standortinformationen im Hintergrund zugreifen.
  • Der Zugangspunkt muss den IEEE 802.11-2016 FTM-Standard implementieren.

Einrichten

Führen Sie die folgenden Schritte aus, um Ihre App für die Verwendung von WLAN-RTT einzurichten.

1. Berechtigungen anfordern

Fordere im Manifest deiner 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 die Berechtigung noch nicht 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 kannst du 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

Möglicherweise ist auf dem Gerät WLAN-RTT vorhanden, ist aber derzeit nicht verfügbar, weil der Nutzer WLAN deaktiviert hat. Je nach ihren Hardware- und Firmware-Fähigkeiten unterstützen einige Geräte möglicherweise keine WLAN-RTT, wenn SoftAP oder Tethering verwendet werden. Rufen Sie isAvailable() auf, um zu prüfen, ob WLAN-RTT derzeit verfügbar ist.

Die Verfügbarkeit von WLAN-RTT kann sich jederzeit ändern. Deine App sollte einen BroadcastReceiver für den Empfang von ACTION_WIFI_RTT_STATE_CHANGED registrieren, der gesendet wird, wenn sich die Verfügbarkeit ändert. Wenn Ihre App den Broadcast-Intent empfängt, sollte sie den aktuellen Verfügbarkeitsstatus prüfen und ihr Verhalten entsprechend anpassen.

Beispiele:

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.

Eine Entfernungsanfrage erstellen

Eine Entfernungsanfrage (RangingRequest) wird durch Angabe einer Liste von ZPs oder Wi-Fi Aware Peers erstellt, für die ein Bereich angefordert wird. In einer einzelnen Entfernungsanfrage 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 anhand seines ScanResult-Objekts identifiziert, das durch Aufrufen von WifiManager.getScanResults() abgerufen werden kann. Du kannst addAccessPoints(List) verwenden, um mehrere Zugangspunkte in einem Batch hinzuzufügen.

In ähnlicher Weise kann bei einer Entfernungsanfrage ein WLAN-sensitiver Peer über seine MAC-Adresse oder sein PeerHandle hinzugefügt werden. Dazu werden die Methoden addWifiAwarePeer(MacAddress Peering) bzw. addWifiAwarePeer(PeerHandle Koppel) verwendet. Weitere Informationen zur Suche nach Wi-Fi Aware-Peers finden Sie in der Wi-Fi Aware-Dokumentation.

Anfragebereich

Eine Anwendung sendet mit der Methode WifiRttManager.startRanging() eine Entfernungsanfrage und stellt Folgendes bereit: einen RangingRequest zur Angabe des Vorgangs, einen Executor zur Angabe des Callback-Kontexts und einen RangingResultCallback zum Empfang der Ergebnisse.

Beispiele:

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

  • Wenn der gesamte Entfernungsvorgang fehlschlägt, wird der Callback onRangingFailure mit einem Statuscode ausgelöst, der in RangingResultCallback beschrieben wird. Ein solcher Fehler kann auftreten, wenn der Dienst zum entsprechenden Zeitpunkt keinen Bereiching-Vorgang ausführen kann, z. B. weil WLAN deaktiviert ist, die Anwendung zu viele Entfernungsvorgänge angefordert und gedrosselt wurde oder ein Berechtigungsproblem vorliegt.
  • Wenn der Entfernungsvorgang abgeschlossen ist, wird der Callback onRangingResults mit einer Liste von Ergebnissen ausgelöst, die mit der Liste der Anfragen übereinstimmt. Dabei handelt es sich um ein Ergebnis für jede Anfrage. Die Reihenfolge der Ergebnisse entspricht nicht unbedingt der Reihenfolge der Anfragen. Der Entfernungsvorgang kann zwar abgeschlossen werden, aber jedes Ergebnis kann dennoch auf einen Fehler bei der jeweiligen Messung hinweisen.

Entfernungsergebnisse 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 Sie beim Erstellen der RangingRequest angegeben haben. Dies ist meistens eine MAC-Adresse aus dem ScanResult, die einen Zugangspunkt identifiziert. Die MAC-Adresse kann mit der Methode getMacAddress() aus dem Entfernungsergebnis abgerufen werden.

Die Liste der Bereichsergebnisse kann in einer anderen Reihenfolge als die Peers (Zugangspunkte) sein, die in der Entfernungsanfrage angegeben sind. Daher sollten Sie zur Identifizierung des Peers und nicht der Reihenfolge der Ergebnisse die MAC-Adresse verwenden.

2. Herausfinden, ob die Messung erfolgreich war

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 der Ausnahme IllegalStateException fehlschlägt.

3. Ergebnisse für jede erfolgreiche Messung erhalten

Für jede erfolgreiche Messung können Sie Ergebniswerte mit den jeweiligen get-Methoden abrufen:

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

In den folgenden Tabellen sind einige Telefone, Zugangspunkte und Geräte im Einzelhandel, in Lagern und in Distributionszentren aufgeführt, die WLAN-RTT unterstützen. Diese sind alles andere als umfassend. Wenn Sie Ihre RTT-fähigen Produkte hier auflisten möchten, wenden Sie sich bitte an uns.

Zugangspunkte

Hersteller und Modell Datum der Unterstützung
Nest Wifi Pro (Wi-Fi 6E) Unterstützt
Compulab WILD AP Unterstützt
Google Wifi Unterstützt
Google Nest-WLAN-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
Google Pixel 6 9,0 oder höher
Google Pixel 6 Pro 9,0 oder höher
Google Pixel 5 9,0 oder höher
Pixel 5a 9,0 oder höher
Pixel 5a (5G) 9,0 oder höher
Xiaomi Mi 10 Pro 9,0 oder höher
Xiaomi Mi 10 9,0 oder höher
Xiaomi Redmi Mi 9T Pro 9,0 oder höher
Xiaomi Mi 9T 9,0 oder höher
Xiaomi Mi 9 9,0 oder höher
Xiaomi Mi Note 10 9,0 oder höher
Xiaomi Mi Note 10 Lite 9,0 oder höher
Xiaomi Redmi Note 9S 9,0 oder höher
Xiaomi Redmi Note 9 Pro 9,0 oder höher
Xiaomi Redmi Note 8T 9,0 oder höher
Xiaomi Redmi Note 8 9,0 oder höher
Xiaomi Redmi K30 Pro 9,0 oder höher
Xiaomi Redmi K20 Pro 9,0 oder höher
Xiaomi Redmi K20 9,0 oder höher
Xiaomi Redmi Note 5 Pro 9,0 oder höher
Xiaomi Mi CC9 Pro 9,0 oder höher
LG G8X ThinQ 9,0 oder höher
LG V50S ThinQ 9,0 oder höher
LG V60 ThinQ 9,0 oder höher
LG V30 9,0 oder höher
Samsung Galaxy Note 10+ 5G 9,0 oder höher
Samsung Galaxy S20+ 5G 9,0 oder höher
Samsung Galaxy S20+ 9,0 oder höher
Samsung Galaxy S20 5G 9,0 oder höher
Samsung Galaxy S20 Ultra 5G 9,0 oder höher
Samsung Galaxy S20 9,0 oder höher
Samsung Galaxy Note 10+ 9,0 oder höher
Samsung Galaxy Note 10 5G 9,0 oder höher
Samsung Galaxy Note 10 9,0 oder höher
Samsung A9 Pro 9,0 oder höher
Google Pixel 4 XL 9,0 oder höher
Google Pixel 4 9,0 oder höher
Google Pixel 4a 9,0 oder höher
Google Pixel 3 XL 9,0 oder höher
Google Pixel 3 9,0 oder höher
Google Pixel 3a XL 9,0 oder höher
Google Pixel 3a 9,0 oder höher
Google Pixel 2 XL 9,0 oder höher
Google Pixel 2 9,0 oder höher
Google Pixel 1 XL 9,0 oder höher
Google Pixel 1 9,0 oder höher
Poco X2 9,0 oder höher
Sharp Aquos R3 SH-04L 9,0 oder höher

Geräte für Einzelhandel, Lagerung und Distributionszentrum

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