Lokalizacja Wi-Fi: w zakresie z RTT

Możesz użyć funkcji lokalizacji Wi-Fi dostępnej w interfejsie API Wi-Fi RTT (Round-Trip-Time), aby zmierzyć odległość od pobliskich punktów dostępu Wi-Fi obsługujących RTT i urządzeń równorzędnych Wi-Fi Aware.

Jeśli mierzysz odległość do co najmniej 3 punktów dostępu, możesz użyć algorytmu mnożnika, aby oszacować położenie urządzenia, które najlepiej pasuje do tych pomiarów. Wynik jest zwykle dokładny do 1–2 metrów.

Dzięki tej dokładności możesz opracowywać szczegółowe usługi oparte na lokalizacji, takie jak nawigacja wewnątrz budynków, jednoznaczne sterowanie głosem (np. „Włącz to światło”) i informacje oparte na lokalizacji (np. „Czy są jakieś oferty specjalne na ten produkt?”).

Urządzenie wysyłające żądanie nie musi łączyć się z punktami dostępu, aby mierzyć odległość za pomocą RTT Wi-Fi. Ze względu na ochronę prywatności tylko urządzenie wysyłające żądanie może określić odległość do punktu dostępu. Punkty dostępu nie mają tych informacji. W przypadku aplikacji działających na pierwszym planie operacje RTT Wi-Fi są nieograniczone, ale w przypadku aplikacji działających w tle są ograniczone.

RTT Wi-Fi i powiązane z nim funkcje dokładnego pomiaru czasu (FTM) są określone w standardzie IEEE 802.11-2016. RTT Wi-Fi wymaga dokładnego pomiaru czasu przez FTM, ponieważ oblicza odległość między dwoma urządzeniami przez pomiar czasu, jaki zajmuje pakiet na przebycie dwukierunkowej trasy między urządzeniami, i pomnożenie tego czasu przez prędkość światła.

W Androidzie 15 (poziom API 35) wprowadzono obsługę pomiaru odległości (NTB) w standardzie IEEE 802.11az.

Różnice w implementacji w zależności od wersji Androida

Wi-Fi RTT zostało wprowadzone w Androidzie 9 (poziom API 28). Jeśli używasz tego protokołu do określania pozycji urządzenia za pomocą wielobocznej lokalizacji na urządzeniach z Androidem 9, musisz mieć w aplikacji dostęp do zdefiniowanych wcześniej danych o lokalizacji punktów dostępu (AP). To od Ciebie zależy, jak te dane będą przechowywane i pobierane.

Na urządzeniach z Androidem 10 (poziom interfejsu API 29) lub nowszym dane o lokalizacji punktu dostępu mogą być przedstawione jako obiekty ResponderLocation, które obejmują szerokość, długość geograficzną i wysokość. W przypadku punktów dostępowych Wi-Fi RTT, które obsługują informacje o konfiguracji lokalizacji lub raporty o lokalizacji (dane LCI/LCR), protokół zwróci obiekt ResponderLocation podczas procesu określania zasięgu.

Ta funkcja umożliwia aplikacjom wysyłanie zapytań do punktów dostępu w celu uzyskania ich położenia bezpośrednio, zamiast przechowywania tych informacji z wyprzedzeniem. Dzięki temu Twoja aplikacja może znajdować punkty dostępu i określać ich pozycje, nawet jeśli nie były one znane wcześniej, na przykład gdy użytkownik wchodzi do nowego budynku.

Obsługa pomiaru odległości NTB w standardzie IEEE 802.11az jest dostępna na urządzeniach z Androidem 15 (poziom interfejsu API 35) lub nowszym. Oznacza to, że jeśli urządzenie obsługuje tryb inicjatora IEEE 802.11az NTB (oznaczony jako WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), aplikacja może znaleźć punkty dostępu obsługujące zarówno IEEE 802.11mc, jak i IEEE 802.11az za pomocą jednej prośby o zakres. Interfejs API RangingResult został rozszerzony o informacje o minimalnej i maksymalnej wartości, która może być używana w przypadku interwału między pomiarami, pozostawiając dokładny interwał pod kontrolą aplikacji.

Wymagania

  • Sprzęt urządzenia wysyłającego żądanie pomiaru zasięgu musi być zgodny ze standardem FTM 802.11-2016 lub standardem 802.11az (pomiar zasięgu bez wyzwalacza).
  • Urządzenie wysyłające żądanie określania zasięgu musi działać na Androidzie 9 (poziom interfejsu API 28) lub nowszym. Na urządzeniach z Androidem 15 (poziom interfejsu API 35) lub nowszym włączone jest określanie odległości za pomocą standardu IEEE 802.11az bez wyzwalacza.
  • Urządzenie wysyłające żądanie pomiaru odległości musi mieć włączone usługi lokalizacyjne i skanowanie sieci Wi-Fi (w sekcji Ustawienia > Lokalizacja).
  • Jeśli aplikacja wysyłająca żądanie określania zakresu jest kierowana na Androida 13 (poziom interfejsu API 33) lub nowszego, musi mieć uprawnienie NEARBY_WIFI_DEVICES. Jeśli taka aplikacja jest przeznaczona na wcześniejszą wersję Androida, musi mieć uprawnienie ACCESS_FINE_LOCATION.
  • Aplikacja musi wysyłać zapytania do zakresu punktów dostępu, gdy jest widoczna lub działa jako usługa na pierwszym planie. Aplikacja nie może uzyskiwać dostępu do informacji o lokalizacji w tle.
  • Punkt dostępu musi stosować standard FTM IEEE 802.11-2016 lub standard IEEE 802.11az (określanie zasięgu bez użycia wyzwalacza).

Konfiguracja

Aby skonfigurować aplikację do korzystania z RTT Wi-Fi, wykonaj te czynności.

1. Prośba o uprawnienia

W pliku manifestu aplikacji poproś o te uprawnienia:

<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" />

Uprawnienia NEARBY_WIFI_DEVICES i ACCESS_FINE_LOCATION są niebezpieczne, dlatego musisz o nie prosić za każdym razem, gdy użytkownik chce przeprowadzić operację skanowania RTT. Jeśli użytkownik nie przyznał jeszcze uprawnień, aplikacja będzie musiała o nie poprosić. Więcej informacji o uprawnieniach czasu działania znajdziesz w artykule Prośba o uprawnienia aplikacji.

2. Sprawdź, czy urządzenie obsługuje Wi-Fi RTT

Aby sprawdzić, czy urządzenie obsługuje RTT przez Wi-Fi, użyj interfejsu API PackageManager:

Kotlin

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

Java

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

3. Sprawdzanie, czy dostępna jest funkcja RTT Wi-Fi

Funkcja RTT Wi-Fi może być dostępna na urządzeniu, ale może być wyłączona, ponieważ użytkownik wyłączył Wi-Fi. W zależności od możliwości sprzętowych i oprogramowania niektóre urządzenia mogą nie obsługiwać RTT w sieci Wi-Fi, jeśli w użyciu jest funkcja SoftAP lub tethering. Aby sprawdzić, czy funkcja RTT przez Wi-Fi jest dostępna, zadzwoń pod numer isAvailable().

Dostępność funkcji RTT w sieci Wi-Fi może się zmienić w każdej chwili. Aplikacja powinna zarejestrować BroadcastReceiver, aby otrzymywać ACTION_WIFI_RTT_STATE_CHANGED, które są wysyłane po zmianie dostępności. Gdy aplikacja otrzyma intencję transmisji, powinna sprawdzić bieżący stan dostępności i odpowiednio dostosować swoje działanie.

Na przykład:

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);

Więcej informacji znajdziesz w artykule Transmisje.

Utwórz prośbę o zakres

Żądanie pomiaru zasięgu (RangingRequest) jest tworzone przez podanie listy punktów dostępu lub urządzeń Wi-Fi Aware, do których jest wysyłane żądanie pomiaru zasięgu. W jednym żądaniu pomiaru odległości można określić wiele punktów dostępu lub urządzeń obsługujących Wi-Fi Aware. W zwrotnej wartości podawana jest odległość do wszystkich urządzeń.

Na przykład żądanie może użyć metody addAccessPoint(), aby określić punkt dostępu, do którego mierzy się odległość:

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();

Punkt dostępu można zidentyfikować po obiekcie ScanResult, który można uzyskać, wywołując funkcję WifiManager.getScanResults(). Możesz użyć addAccessPoints(List<ScanResult>), aby dodać wiele punktów dostępu w grupie.

Obiekty ScanResult mogą zawierać punkty dostępowe obsługujące zarówno standard IEEE 802.11mc (is80211mcResponder()), jak i standard IEEE 802.11az (is80211azNtbResponder()) z obsługą pomiarów bez wyzwalania. Urządzenia, które obsługują pomiar zasięgu NTB w standardzie IEEE 802.11az, wykonują pomiar zasięgu w standardzie 802.11mc lub 802.11az w zależności od możliwości punktu dostępu. Domyślnie jest używany standard 802.11az, jeśli punkt dostępu obsługuje oba standardy. Urządzenia, które nie obsługują standardu IEEE 802.11az, wykonują wszystkie pomiary zasięgu przy użyciu protokołu IEEE 802.11mc.

Podobnie żądanie pomiaru zasięgu może dodać urządzenie obsługujące Wi-Fi Aware, używając adresu MAC lub PeerHandle, odpowiednio za pomocą metod addWifiAwarePeer(MacAddress peer) i addWifiAwarePeer(PeerHandle peer). Więcej informacji o wykrywaniu urządzeń Wi-Fi Aware znajdziesz w dokumentacji Wi-Fi Aware.

Żądanie określenia zasięgu

Aplikacja wysyła żądanie pomiaru za pomocą metody WifiRttManager.startRanging(), podając: RangingRequest, aby określić operację, Executor, aby określić kontekst wywołania zwrotnego, oraz RangingResultCallback, aby otrzymać wyniki.

Na przykład:

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) {  }
});

Operacja określania zakresu jest wykonywana asynchronicznie, a wyniki określania zakresu są zwracane w jednym z wywołań zwrotnych funkcji RangingResultCallback:

  • Jeśli cała operacja pomiaru odległości zakończy się niepowodzeniem, wywołanie zwrotne onRangingFailure zostanie wywołane z kodem stanu opisanym w RangingResultCallback. Taki błąd może wystąpić, jeśli usługa nie może wykonać operacji pomiaru odległości w danym momencie, np. dlatego, że Wi-Fi jest wyłączone, aplikacja poprosiła o zbyt wiele operacji pomiaru odległości i została ograniczona lub z powodu problemu z uprawnieniami.
  • Po zakończeniu operacji określania zasięgu wywoływana jest funkcja onRangingResults z listą wyników odpowiadającą liście żądań – po jednym wyniku na każde żądanie. Kolejność wyników nie musi być zgodna z kolejnością żądań. Pamiętaj, że pomiar zasięgu może się zakończyć, ale każdy wynik może wskazywać na nieprawidłowość danego pomiaru.

Interpretowanie wyników pomiarów zasięgu

Każdy z wyników zwracanych przez funkcję wywołania zwrotnego onRangingResults jest określony przez obiekt RangingResult. W przypadku każdego żądania wykonaj te czynności.

1. Identyfikacja żądania

Zidentyfikuj żądanie na podstawie informacji podanych podczas tworzenia obiektu RangingRequest. Zazwyczaj jest to adres MAC podany w polu ScanResult identyfikujący punkt dostępu. Adres MAC można uzyskać z wyników pomiaru zasięgu za pomocą metody getMacAddress().

Lista wyników pomiaru zasięgu może być w innej kolejności niż punkty dostępu (peery) określone w żądaniu pomiaru zasięgu, dlatego do identyfikacji peera należy użyć adresu MAC, a nie kolejności wyników.

2. sprawdzać, czy każdy pomiar się udał.

Aby sprawdzić, czy pomiar się udał, użyj metody getStatus(). Każda wartość inna niż STATUS_SUCCESS oznacza błąd. Błąd oznacza, że wszystkie inne pola tego wyniku (z wyjątkiem identyfikatora żądania) są nieprawidłowe, a odpowiednia metoda get* zakończy się błędem z wyjątkiem IllegalStateException.

3. Pobieranie wyników każdego udanego pomiaru

W przypadku każdego udanego pomiaru (RangingResult) możesz pobierać wartości wyników za pomocą odpowiednich metod get:

  • Odległość w mm i odchylenie standardowe pomiaru:

    getDistanceMm()

    getDistanceStdDevMm()

  • RSSI pakietów użytych do pomiarów:

    getRssi()

  • Czas w milisekundach, w którym dokonano pomiaru (czas od rozruchu):

    getRangingTimestampMillis()

  • Liczba prób pomiarów i liczba pomiarów, które zakończyły się powodzeniem (i na których opierają się pomiary odległości):

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • Minimalny i maksymalny czas oczekiwania urządzenia klienta między pomiarami 11az NTB:

    getMinTimeBetweenNtbMeasurementsMicros() i getMaxTimeBetweenNtbMeasurementsMicros() zwracają minimalny i maksymalny czas. Jeśli następne żądanie pomiaru zasięgu zostanie wysłane przed upłynięciem minimalnego czasu, interfejs API zwróci wynik pomiaru zasięgu z pamięci podręcznej. Jeśli żądanie kolejnego pomiaru zakresu zostanie wysłane po upłynięciu maksymalnego czasu, interfejs API zakończy sesję niezawierającą aktywatorów i wynegocjuje nową sesję określania zakresu z reagującą stacją. Nie zalecamy żądania nowej sesji pomiaru zasięgu, ponieważ wydłuża to czas pomiaru zasięgu. Aby w pełni wykorzystać wydajność pomiaru zasięgu w standardzie 802.11az bez korzystania z wyzwalacza, wyślij kolejne żądanie pomiaru zasięgu w czasie od minimalnego do maksymalnego czasu pomiaru określonego w poprzednim pomiarze RangingResult.

  • Powtórzenia długiego pola treningowego (LTF), które stacje odpowiadające i inicjujące używają w preambule w przypadku wyniku NTB IEEE 802.11az:

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • Liczba strumieni czasowych przestrzennych (STS) do przesyłania i odbierania, których używa inicjator stacji do wyniku NTB IEEE 802.11az:

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Urządzenia z Androidem, które obsługują WiFi-RTT

W tabelach poniżej znajdziesz listę niektórych telefonów, punktów dostępuurządzeń do sprzedaży detalicznej, magazynowania i centrum dystrybucji, które obsługują WiFi-RTT. Nie są one w żaden sposób wyczerpujące. Zachęcamy do kontaktowania się z nami, aby zgłosić produkty obsługujące RTT.

Punkty dostępu

Producent i model Data wsparcia
Nest Wifi Pro (Wi-Fi 6E) Obsługiwane
Compulab WILD AP Obsługiwane
Google Wi-Fi Obsługiwane
router Wi-Fi Google Nest Obsługiwane
Punkt dostępu Google Nest Wi-Fi Obsługiwane
Aruba AP-635 Obsługiwane
Cisco 9130 Obsługiwane
Cisco 9136 Obsługiwane
Cisco 9166 Obsługiwane
Cisco 9164 Obsługiwane
Aruba AP-505 Obsługiwane
Aruba AP-515 Obsługiwane
Aruba AP-575 Obsługiwane
Aruba AP-518 Obsługiwane
Aruba AP-505H Obsługiwane
Aruba AP-565 Obsługiwane
Aruba AP-535 Obsługiwane

Telefony

Producent i model Wersja Androida
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+

Urządzenia do sklepów, magazynów i centrów dystrybucyjnych

Producent i model Wersja Androida
Zebra PS20 10,0+
Zebra TC52/TC52HC 10,0+
Zebra TC57 10.0 lub nowszy
Zebra TC72 10,0+
Zebra TC77 10,0+
Zebra MC93 10.0 lub nowszy
Zebra TC8300 10,0+
Zebra VC8300 10,0+
Zebra EC30 10.0 lub nowszy
Zebra ET51 10,0+
Zebra ET56 10,0+
Zebra L10 10.0 lub nowszy
Zebra CC600/CC6000 10,0+
Zebra MC3300x 10,0+
Zebra MC330x 10.0 lub nowszy
Zebra TC52x 10,0+
Zebra TC57x 10.0 lub nowszy
Zebra EC50 (LAN i HC) 10,0+
Zebra EC55 (WAN) 10.0 lub nowszy
Zebra WT6300 10,0+
Skorpio X5 10,0+