Lokalizacja Wi-Fi: w zakresie z RTT

Możesz użyć funkcji lokalizacji Wi-Fi udostępnianej przez interfejs Wi-Fi RTT (Round-Trip-Time) API, aby mierzyć odległość od pobliskich punktów dostępowych Wi-Fi obsługujących RTT i urządzeń peer Wi-Fi Aware.

Jeśli zmierzysz odległość od co najmniej 3 punktów dostępu, możesz użyć algorytmu multilateracji, aby oszacować pozycję urządzenia, która najlepiej pasuje do tych pomiarów. Wynik jest zwykle dokładny w zakresie 1–2 metrów.

Dzięki tej dokładności możesz tworzyć precyzyjne usługi oparte na lokalizacji, takie jak nawigacja w pomieszczeniach, sterowanie głosowe z rozróżnianiem kontekstu (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 zmierzyć odległość za pomocą Wi-Fi RTT. Aby zachować prywatność, tylko urządzenie wysyłające żądanie może określić odległość od punktu dostępu. Punkty dostępu nie mają tych informacji. Operacje Wi-Fi RTT są nieograniczone w przypadku aplikacji działających na pierwszym planie, ale są ograniczane w przypadku aplikacji działających w tle.

Wi-Fi RTT i powiązane z nim funkcje precyzyjnego pomiaru czasu (FTM) są określone w standardzie IEEE 802.11-2016. Wi-Fi RTT wymaga precyzyjnego pomiaru czasu zapewnianego przez FTM, ponieważ oblicza odległość między dwoma urządzeniami, mierząc czas, jaki pakiet potrzebuje na podróż w obie strony między urządzeniami, i mnożąc ten czas przez prędkość światła.

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

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

Wi-Fi RTT zostało wprowadzone w Androidzie 9 (poziom interfejsu API 28). Jeśli używasz tego protokołu do określania pozycji urządzenia za pomocą multilateracji na urządzeniach z Androidem 9, musisz mieć w aplikacji dostęp do wstępnie określonych lokalizacji punktów dostępu. To Ty decydujesz, jak przechowywać i pobierać te dane.

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

Ta funkcja umożliwia aplikacjom wysyłanie zapytań do punktów dostępu o ich pozycję bezpośrednio, zamiast przechowywać te informacje z wyprzedzeniem. Dzięki temu aplikacja może znajdować punkty dostępu i określać ich położenie nawet wtedy, gdy nie były wcześniej znane, np. gdy użytkownik wejdzie 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 API 35) i nowszym. Oznacza to, że jeśli urządzenie obsługuje tryb inicjatora IEEE 802.11az NTB (wskazywany przez WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), aplikacja może znaleźć punkty dostępu obsługujące IEEE 802.11mc i IEEE 802.11az za pomocą jednego żądania zakresu. Interfejs RangingResult API został rozszerzony, aby dostarczać informacji o minimalnej i maksymalnej wartości, która może być używana w przypadku odstępu między pomiarami odległości. Dokładny odstęp jest kontrolowany przez aplikację.

Wymagania

  • Sprzęt urządzenia wysyłającego żądanie pomiaru odległości musi być zgodny ze standardem 802.11-2016 FTM lub 802.11az (pomiar odległości bez wyzwalania).
  • Urządzenie wysyłające żądanie określenia odległości musi mieć Androida 9 (poziom API 28) lub nowszego. Na urządzeniach z Androidem 15 (poziom interfejsu API 35) lub nowszym włączone jest określanie odległości bez wyzwalania zgodnie ze standardem IEEE 802.11az.
  • Urządzenie wysyłające żądanie pomiaru odległości musi mieć włączone usługi lokalizacyjne i skanowanie Wi-Fi (w Ustawieniach > Lokalizacja).
  • Jeśli aplikacja, która wysyła żądanie określenia zakresu, jest kierowana na Androida 13 (API na poziomie 33) lub nowszego, musi mieć uprawnienie NEARBY_WIFI_DEVICES. Jeśli taka aplikacja jest przeznaczona na starszą wersję Androida, musi mieć uprawnienie ACCESS_FINE_LOCATION.
  • Aplikacja musi wysyłać zapytania o zakres punktów dostępu, gdy jest widoczna lub działa jako usługa na pierwszym planie. Aplikacja nie może uzyskiwać informacji o lokalizacji w tle.
  • Punkt dostępu musi implementować standard IEEE 802.11-2016 FTM lub IEEE 802.11az (pomiar odległości bez wyzwalania).

Konfiguracja

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

1. Prośba o uprawnienia

Poproś o te uprawnienia w pliku manifestu aplikacji:

<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_DEVICESACCESS_FINE_LOCATION są uprawnieniami niebezpiecznymi, więc musisz o nie prosić w czasie działania aplikacji za każdym razem, gdy użytkownik chce przeprowadzić skanowanie RTT. Jeśli uprawnienia nie zostały jeszcze przyznane, aplikacja musi poprosić użytkownika o wyrażenie zgody. Więcej informacji o uprawnieniach czasu działania znajdziesz w artykule Request App Permissions (Prośba o uprawnienia aplikacji).

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

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

Kotlin

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

Java

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

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

Funkcja Wi-Fi RTT może być dostępna na urządzeniu, ale może nie działać, 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ć Wi-Fi RTT, jeśli używany jest punkt dostępu lub tethering. Aby sprawdzić, czy funkcja Wi-Fi RTT jest dostępna, zadzwoń pod numer isAvailable().

Dostępność Wi-Fi RTT może się zmienić w dowolnym momencie. Aplikacja powinna zarejestrować BroadcastReceiver, aby otrzymywać ACTION_WIFI_RTT_STATE_CHANGED, które jest wysyłane, gdy zmienia się dostępność. 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 sekcji Transmisje.

Tworzenie żądania pomiaru odległości

Żądanie pomiaru odległości (RangingRequest) jest tworzone przez określenie listy punktów dostępu lub urządzeń Wi-Fi Aware, do których ma być zmierzona odległość. W jednym żądaniu pomiaru odległości można określić wiele punktów dostępu lub urządzeń równorzędnych Wi-Fi Aware. Mierzone i zwracane są odległości do wszystkich urządzeń.

Na przykład żądanie może używać metody addAccessPoint() do określania punktu dostępu, od którego ma być mierzona 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 jest identyfikowany przez obiekt ScanResult, który można uzyskać, wywołując funkcję WifiManager.getScanResults(). Możesz użyć addAccessPoints(List<ScanResult>) do dodania wielu punktów dostępu w ramach jednej operacji.

Obiekty ScanResult mogą zawierać punkty dostępu obsługujące zarówno standard IEEE 802.11mc (is80211mcResponder()), jak i standard IEEE 802.11az non-trigger based ranging (is80211azNtbResponder()). Urządzenia obsługujące pomiar odległości NTB w standardzie IEEE 802.11az wykonują pomiar odległości w standardzie 802.11mc lub 802.11az w zależności od możliwości punktu dostępu. Jeśli punkt dostępu obsługuje oba standardy, domyślnie używany jest standard 802.11az. Urządzenia, które nie obsługują standardu IEEE 802.11az, wykonują wszystkie pomiary odległości za pomocą protokołu IEEE 802.11mc.

Podobnie żądanie określenia odległości może dodać urządzenie Wi-Fi Aware, używając jego adresu MAC lub PeerHandle, odpowiednio za pomocą metod addWifiAwarePeer(MacAddress peer)addWifiAwarePeer(PeerHandle peer). Więcej informacji o wykrywaniu urządzeń równorzędnych Wi-Fi Aware znajdziesz w dokumentacji Wi-Fi Aware.

Żądanie pomiaru odległości

Aplikacja wysyła żądanie pomiaru odległości za pomocą metody WifiRttManager.startRanging(), podając: RangingRequest określający operację, Executor określający kontekst wywołania zwrotnego i RangingResultCallback do odbierania wyników.

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 odległości jest wykonywana asynchronicznie, a wyniki są zwracane w jednym z wywołań zwrotnych RangingResultCallback:

  • Jeśli cała operacja określania odległości się nie powiedzie, wywoływane jest wywołanie zwrotne onRangingFailure z kodem stanu opisanym w sekcji RangingResultCallback. Taka sytuacja może wystąpić, jeśli usługa nie może w danym momencie wykonać operacji pomiaru odległości, np. z powodu wyłączonej sieci Wi-Fi, zbyt dużej liczby żądań pomiaru odległości wysłanych przez aplikację (co spowodowało ograniczenie liczby żądań) lub problemu z uprawnieniami.
  • Po zakończeniu operacji określania odległości wywoływana jest funkcja zwrotna onRangingResults z listą wyników, która odpowiada liście żądań – po jednym wyniku dla każdego żądania. Kolejność wyników nie musi być zgodna z kolejnością żądań. Pamiętaj, że operacja pomiaru odległości może się zakończyć, ale każdy wynik może nadal wskazywać na niepowodzenie tego konkretnego pomiaru.

Interpretowanie wyników pomiaru odległości

Każdy wynik zwrócony przez wywołanie zwrotne onRangingResults jest określony przez obiekt RangingResult. Przy każdym żądaniu wykonaj te czynności:

1. Określanie żądania

Zidentyfikuj prośbę na podstawie informacji podanych podczas tworzenia RangingRequest: najczęściej jest to adres MAC podany w ScanResult identyfikujący punkt dostępu. Adres MAC można uzyskać z wyniku pomiaru odległości za pomocą metody getMacAddress().

Lista wyników pomiaru odległości może być w innej kolejności niż punkty dostępu określone w żądaniu pomiaru odległości, dlatego do identyfikowania urządzenia równorzędnego należy używać adresu MAC, a nie kolejności wyników.

2. Określanie, czy każdy pomiar zakończył się powodzeniem

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

3. Uzyskiwanie wyników każdego udanego pomiaru

W przypadku każdego pomiaru zakończonego powodzeniem (RangingResult) możesz pobrać wartości wyników za pomocą odpowiednich metod get:

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

    getDistanceMm()

    getDistanceStdDevMm()

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

    getRssi()

  • Czas w milisekundach, w którym wykonano pomiar (wskazujący czas od uruchomienia):

    getRangingTimestampMillis()

  • Liczba prób pomiaru i liczba pomiarów, które się powiodły (na podstawie których obliczane są odległości):

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • Minimalny i maksymalny czas, przez jaki urządzenie klienta musi czekać między pomiarami 11az NTB:

    getMinTimeBetweenNtbMeasurementsMicros() i getMaxTimeBetweenNtbMeasurementsMicros() zwracają minimalny i maksymalny czas. Jeśli kolejne pomiary odległości zostaną wykonane przed upływem minimalnego czasu, interfejs API zwróci wynik pomiaru z pamięci podręcznej. Jeśli kolejne pomiary odległości zostaną zażądane po upływie maksymalnego czasu, interfejs API zakończy sesję pomiarów odległości bez wyzwalania i uzgodni nową sesję pomiarów odległości ze stacją odpowiadającą. Unikaj przesyłania żądań nowej sesji pomiarowej, ponieważ wydłuża to czas pomiaru. Aby w pełni wykorzystać efektywność pomiarów odległości opartych na standardzie 802.11az bez wyzwalania, wywołaj kolejne żądanie pomiaru odległości w czasie między minimalnym a maksymalnym czasem pomiaru określonym w poprzednim pomiarze RangingResult.

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

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • Liczba strumieni przestrzenno-czasowych (STS) transmisji i odbioru, których stacja inicjująca użyła w przypadku wyniku NTB IEEE 802.11az:

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Urządzenia z Androidem obsługujące WiFi-RTT

W poniższych tabelach znajdziesz listę telefonów, punktów dostępuurządzeń do sprzedaży detalicznej, magazynowania i centrów dystrybucji obsługujących Wi-Fi RTT. Nie są one wyczerpujące. Zachęcamy do skontaktowania się z nami, aby umieścić tutaj swoje produkty obsługujące RTT.

Punkty dostępu

Producent i model Data pomocy Protokół
Nest Wifi Pro (Wi-Fi 6E) Obsługiwane mc
Compulab WILD AP Obsługiwane mc
Google Wi-Fi Obsługiwane mc
Router Google Nest Wi-Fi Obsługiwane mc
Punkt Google Nest Wi-Fi Obsługiwane mc
Aruba AP-635 Obsługiwane mc
Cisco 9130 Obsługiwane mc
Cisco 9136 Obsługiwane mc
Cisco 9166 Obsługiwane mc
Cisco 9164 Obsługiwane mc
Cisco CW9172I Obsługiwane mc/az
Cisco CW9172H Obsługiwane mc/az
Cisco CW9176I Obsługiwane mc/az
Cisco CW9178I Obsługiwane mc/az
Aruba AP-505 Obsługiwane mc
Aruba AP-515 Obsługiwane mc
Aruba AP-575 Obsługiwane mc
Aruba AP-518 Obsługiwane mc
Aruba AP-505H Obsługiwane mc
Aruba AP-565 Obsługiwane mc
Aruba AP-535 Obsługiwane mc
Aruba AP567 Obsługiwane mc
Aruba AP577 Obsługiwane mc
Aruba AP555 Obsługiwane mc
Aruba AP635 Obsługiwane mc
Aruba AP655 Obsługiwane mc
Aruba AP615 Obsługiwane mc
Aruba AP734 Obsługiwane mc/az
Aruba AP735 Obsługiwane mc/az
Aruba AP754 Obsługiwane mc/az
Aruba AP755 Obsługiwane mc/az

Telefony

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

Urządzenia w sklepach detalicznych, magazynach i centrach dystrybucji

Producent i model Wersja Androida
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 i HC) 10.0+
Zebra EC55 (WAN) 10.0+
Zebra WT6300 10.0+
Skorpio X5 10.0+