Sie können die WLAN-Standortfunktion der Wi-Fi RTT (Round-Trip-Time) API verwenden, um die Entfernung zu RTT-fähigen WLAN-Zugangspunkten in der Nähe und Peer-Wi-Fi Aware-Geräten zu messen.
Wenn Sie die Entfernung zu drei oder mehr Zugangspunkten messen, können Sie 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 bis 2 Meter genau.
Mit dieser Genauigkeit lassen sich detaillierte standortbasierte Dienste entwickeln, z. B. Indoor-Navigation, eindeutige Sprachsteuerung (z. B. „Licht einschalten“) und standortbasierte Informationen (z. B. „Gibt es für dieses Produkt Sonderangebote?“).
Das anfragende Gerät muss keine Verbindung zu den Zugangspunkten herstellen, 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 Anwendungen im Vordergrund unbegrenzt, werden jedoch für Hintergrundanwendungen gedrosselt.
Wi-Fi-RTT und die damit verbundenen Fine-Time-Measurement (FTM)-Funktionen werden durch den Standard IEEE 802.11-2016 angegeben. WLAN-RTT erfordert die genaue Zeitmessung von FTM, da sie die Entfernung zwischen zwei Geräten berechnet, indem die Zeit gemessen wird, die ein Paket für den Umlauf zwischen den Geräten benötigt, und diese Zeit mit der Lichtgeschwindigkeit multipliziert.
Implementierungsunterschiede je nach Android-Version
WLAN-RTT wurde mit Android 9 (API-Level 28) eingeführt. Wenn Sie dieses Protokoll verwenden, um die Position eines Geräts durch Multilateration mit Geräten mit Android 9 zu bestimmen, benötigen Sie Zugriff auf vordefinierte AP-Standortdaten in Ihrer App. Sie entscheiden selbst, wie diese Daten gespeichert und abgerufen werden sollen.
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-APs, die Location Configuration Information/Location Civic Report (LCI-/LCR-Daten) unterstützen, gibt das Protokoll während des Entfernungsvorgangs ein ResponderLocation
-Objekt zurück.
Mit dieser Funktion können Apps Zugangspunkte abfragen, um sie direkt nach ihrer Position zu fragen, anstatt diese Informationen im Voraus zu speichern. Ihre App kann also Zugangspunkte finden und ihre Position bestimmen, auch wenn diese zuvor 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, von dem die Entfernungsanfrage gesendet wird, muss Android 9 (API-Level 28) oder höher ausgeführt werden.
- Auf dem Gerät, von dem die Standortermittlungsanfrage gesendet wird, müssen die Standortdienste und die WLAN-Suche (unter Einstellungen > Standort) aktiviert sein.
- Wenn die App, die die Anfrage zur Bereichsauswahl 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 BerechtigungACCESS_FINE_LOCATION
haben. - Die App muss den Bereich der Zugangspunkte abfragen, während sie sichtbar ist oder in einem 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 implementieren.
Einrichten
Führen Sie die folgenden Schritte aus, um Ihre App für die Verwendung von WLAN-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, die Sie jedes Mal zur Laufzeit anfordern müssen, wenn der Nutzer einen RTT-Scanvorgang ausführen möchte. Ihre App muss die Berechtigung des Nutzers anfordern, falls diese 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
Verwenden Sie die PackageManager API, um zu 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. Verfügbarkeit von WLAN-RTT prüfen
WLAN-RTT ist möglicherweise auf dem Gerät vorhanden, aber derzeit nicht verfügbar, da der Nutzer WLAN deaktiviert hat. Je nach Hardware- und Firmwarefunktionen unterstützen einige Geräte möglicherweise WLAN-RTT nicht, wenn SoftAP oder Tethering verwendet wird. Wenn Sie prüfen möchten, ob WLAN-RTT derzeit verfügbar ist, rufen Sie isAvailable() auf.
Die Verfügbarkeit von WLAN-RTT kann sich jederzeit ändern. Deine App sollte einen BroadcastReceiver registrieren, um ACTION_WIFI_RTT_STATE_CHANGED zu empfangen. Dieser Vorgang wird gesendet, 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 Broadcasts.
Bereichsabfrage erstellen
Eine Bereichsanfrage (RangingRequest) wird erstellt, indem eine Liste von ZPs oder Wi-Fi Aware-Peers angegeben wird, 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 durch sein ScanResult-Objekt identifiziert, das durch Aufrufen von WifiManager.getScanResults() abgerufen werden kann. Mit addAccessPoints(List
In ähnlicher Weise kann mit einer Anfrage zur Bereichserkennung ein Wi-Fi Aware-Peer über seine MAC-Adresse oder sein PeerHandle mit den Methoden addWifiAwarePeer(MacAddress Peer) bzw. addWifiAwarePeer(PeerHandle Peer) hinzugefügt werden. Weitere Informationen zur Suche nach Wi-Fi Aware-Peers finden Sie in der Dokumentation zu Wi-Fi Aware.
Bereichsauswahl anfordern
Eine Anwendung sendet mithilfe der Methode WifiRttManager.startRanging() eine Anfrage zur Bereichsauswahl und stellt Folgendes bereit: eine RangingRequest zum Angeben des Vorgangs, einen Executor zum Angeben des Callback-Kontexts 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 Vorgang zur Bereichsbestimmung wird asynchron durchgeführt und die Ergebnisse der Bereichsbestimmung werden in einem der Rückrufe von RangingResultCallback zurückgegeben:
- Wenn der gesamte Bereichserkennungsvorgang fehlschlägt, wird der onRangingFailure-Callback mit einem Statuscode ausgelöst, der unter 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.
- Nach Abschluss des Bereichserkennungsvorgangs wird der onRangingResults-Callback mit einer Liste von Ergebnissen ausgelöst, die mit der Liste der Anfragen übereinstimmen – ein Ergebnis für jede Anfrage. Die Reihenfolge der Ergebnisse stimmt nicht unbedingt mit der Reihenfolge der Anfragen überein. Beachten Sie, dass der Bereichserkennungsvorgang abgeschlossen sein kann, aber jedes Ergebnis kann dennoch auf einen Fehler bei dieser spezifischen Messung hinweisen.
Bereichsergebnisse interpretieren
Alle Ergebnisse, die vom onRangingResults-Callback zurückgegeben werden, werden 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 von RangingRequest angegeben wurden. Dies ist meist eine MAC-Adresse im ScanResult
, die einen Zugangspunkt identifiziert. Die MAC-Adresse kann mit der Methode getMacAddress() aus dem Bereichsergebnis 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. Ermitteln, 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 obigen Anfrageidentifikation) ungültig sind. Die entsprechende Methode get*
schlägt mit der Ausnahme IllegalStateException fehl.
3. Ergebnisse für jede erfolgreiche Messung abrufen
Für jede erfolgreiche Messung können Sie Ergebniswerte mit den entsprechenden get
-Methoden abrufen:
Entfernung in mm und Standardabweichung des Messwerts:
RSSI der für die Messungen verwendeten Pakete:
Zeit in Millisekunden, zu der die Messung durchgeführt wurde (Zeitangabe seit dem Start):
Anzahl der durchgeführten Messungen und Anzahl der erfolgreich durchgeführten Messungen (und auf denen die Entfernungsmessungen basieren):
getNumSuccessfulMeasurements() (Erfolgreich messen)
Android-Geräte, die WiFi-RTT unterstützen
In den folgenden Tabellen sind einige Smartphones, Zugangspunkte sowie Geräte in den Bereichen Einzelhandel, Warehousing und Distribution Center aufgeführt, die WLAN-RTT unterstützen. Das ist alles andere als umfangreich. Wir empfehlen Ihnen, sich an uns zu wenden, um Ihre RTT-fähigen Produkte hier aufzulisten.
Zugangspunkte
Hersteller und Modell | Supportdatum |
---|---|
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 |
---|---|
Pixel 6 | 9.0 oder höher |
Pixel 6 Pro | 9.0 oder höher |
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 Vertrieb
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+ |
WT6300 | 10,0+ |
Skorpio X5 | 10,0+ |