Puoi utilizzare la funzionalità di geolocalizzazione Wi-Fi fornita dall'API Wi-Fi RTT (Round-Trip-Time) per misurare la distanza dai punti di accesso Wi-Fi compatibili con RTT e dai dispositivi peer Wi-Fi Aware nelle vicinanze.
Se misuri la distanza da tre o più punti di accesso, puoi utilizzare un algoritmo di trilaterazione per stimare la posizione del dispositivo più adatta a queste misurazioni. Il risultato è in genere preciso entro 1-2 metri.
Con questa precisione, puoi sviluppare servizi basati sulla posizione granulari, come la navigazione al chiuso, il controllo vocale disambiguato (ad esempio, "Accendi questa lampada") e le informazioni basate sulla posizione (ad esempio, "Ci sono offerte speciali per questo prodotto?").
Il dispositivo richiedente non deve necessariamente connettersi ai punti di accesso per misurare la distanza con RTT Wi-Fi. Per mantenere la privacy, solo il dispositivo che effettua la richiesta è in grado di determinare la distanza dal punto di accesso. I punti di accesso non dispongono di queste informazioni. Le operazioni RTT Wi-Fi sono illimitate per le app in primo piano, ma sono limitate per le app in background.
Il RTT Wi-Fi e le relative funzionalità di misurazione del tempo fine (FTM) sono specificati dallo standard IEEE 802.11-2016. Wi-Fi RTT richiede la misurazione precisa del tempo fornita da FTM perché calcola la distanza tra due dispositivi misurando il tempo impiegato da un pacchetto per compiere un viaggio di andata e ritorno tra i dispositivi e moltiplicando il tempo per la velocità della luce.
Android 15 (livello API 35) ha introdotto il supporto della misurazione della distanza basata su trigger (NTB) IEEE 802.11az.
Differenze di implementazione in base alla versione di Android
La RTT Wi-Fi è stata introdotta in Android 9 (livello API 28). Quando utilizzi questo protocollo per determinare la posizione di un dispositivo tramite la trilaterazione con dispositivi che eseguono Android 9, devi avere accesso ai dati predeterminati relativi alla posizione dei punti di accesso (AP) nella tua app. Sta a te decidere come memorizzare e recuperare questi dati.
Sui dispositivi con Android 10 (livello API 29) e versioni successive, i dati sulla posizione dell'AP possono essere rappresentati come oggetti ResponderLocation
, che includono latitudine, longitudine e altitudine. Per gli AP RTT Wi-Fi che supportano i dati LCI/LCR (Location Configuration Information/Location Civic Report), il protocollo restituirà un oggetto ResponderLocation
durante la procedura di misurazione della distanza.
Questa funzionalità consente alle app di eseguire query sugli AP per chiedere direttamente la loro posizione, anziché dover memorizzare queste informazioni in anticipo. Di conseguenza, l'app può trovare gli AP e determinarne le posizioni anche se questi non erano noti prima, ad esempio quando un utente entra in un nuovo edificio.
Il supporto della misurazione della distanza NTB IEEE 802.11az è disponibile sui dispositivi con Android 15
(livello API 35) e versioni successive. Ciò significa che se il dispositivo supporta la modalità di iniziatore NTB IEEE 802.11az (indicata da WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR
), la tua app può trovare AP compatibili sia con IEEE 802.11mc che con IEEE 802.11az con una singola richiesta di intervallo. L'API RangingResult
è stata estesa per fornire informazioni
sul valore minimo e massimo che può essere utilizzato per l'intervallo tra
misurazioni diverse, lasciando l'intervallo esatto sotto il controllo dell'app.
Requisiti
- L'hardware del dispositivo che effettua la richiesta di misurazione della distanza deve implementare lo standard FTM 802.11-2016 o lo standard 802.11az (misurazione della distanza non basata su trigger).
- Sul dispositivo che effettua la richiesta di portata deve essere installato Android 9 (livello API 28) o versioni successive. L'intervallo non basato su trigger IEEE 802.11az è abilitato sui dispositivi con Android 15 (livello API 35) e versioni successive.
- Sul dispositivo che effettua la richiesta di misurazione della distanza devono essere attivati i servizi di geolocalizzazione e la ricerca di reti Wi-Fi (in Impostazioni > Posizione).
- Se l'app che effettua la richiesta di misurazione della distanza ha come target Android 13 (livello API 33) o versioni successive, deve disporre dell'autorizzazione
NEARBY_WIFI_DEVICES
. Se un'app di questo tipo ha come target una versione precedente di Android, deve avere invece l'autorizzazioneACCESS_FINE_LOCATION
. - L'app deve eseguire una query sull'intervallo di punti di accesso mentre è visibile o in un servizio in primo piano. L'app non può accedere ai dati sulla posizione in background.
- Il punto di accesso deve implementare lo standard FTM IEEE 802.11-2016 o lo standard IEEE 802.11az (roaming non basato su trigger).
Configura
Per configurare l'app in modo che utilizzi il RTT Wi-Fi, svolgi i seguenti passaggi.
1. Richiedi autorizzazioni
Richiedi le seguenti autorizzazioni nel file manifest dell'app:
<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" />
Le autorizzazioni NEARBY_WIFI_DEVICES
e ACCESS_FINE_LOCATION
sono autorizzazioni pericolose, quindi devi richiederle in fase di runtime ogni volta che l'utente vuole eseguire un'operazione di scansione RTT. L'app dovrà richiedere l'autorizzazione dell'utente se non è già stata concessa. Per ulteriori informazioni sulle autorizzazioni di runtime, vedi Richiedere le autorizzazioni per le app.
2. Verificare se il dispositivo supporta il RTT Wi-Fi
Per verificare se il dispositivo supporta il RTT Wi-Fi, utilizza l'API
PackageManager
:
Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
3. Verificare se il RTT Wi-Fi è disponibile
Il dispositivo potrebbe disporre di RTT Wi-Fi, che però potrebbe non essere disponibile perché l'utente ha disattivato il Wi-Fi. A seconda delle funzionalità hardware e del firmware, alcuni dispositivi potrebbero non supportare il RTT Wi-Fi se sono in uso SoftAP o il tethering. Per verificare se la funzionalità RTT Wi-Fi è disponibile, chiama isAvailable()
.
La disponibilità del RTT Wi-Fi può cambiare in qualsiasi momento. La tua app deve registrare un
BroadcastReceiver
per ricevere
ACTION_WIFI_RTT_STATE_CHANGED
,
che viene inviato quando la disponibilità cambia. Quando l'app riceve l'intent di trasmissione, deve controllare lo stato corrente della disponibilità e modificare il proprio comportamento di conseguenza.
Ad esempio:
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);
Per ulteriori informazioni, consulta la sezione Trasmissioni.
Crea una richiesta di misurazione
Viene creata una richiesta di misurazione della distanza (RangingRequest
) specificando un elenco di AP o peer Wi-Fi Aware a cui viene richiesta una misurazione della distanza. È possibile specificare più punti di accesso o peer Wi-Fi Aware in una singola richiesta di misurazione della distanza; le distanze da tutti i dispositivi vengono misurate e restituite.
Ad esempio, una richiesta può utilizzare il metodo
addAccessPoint()
per specificare un punto di accesso a cui misurare la distanza:
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();
Un punto di accesso viene identificato dall'oggetto
ScanResult
, che può essere ottenuto chiamando
WifiManager.getScanResults()
.
Puoi utilizzare
addAccessPoints(List<ScanResult>)
per aggiungere più punti di accesso in blocco.
Gli oggetti ScanResult
possono contenere AP supportati sia con IEEE 802.11mc (is80211mcResponder()
) sia con misurazione della distanza basata su trigger non IEEE 802.11az (is80211azNtbResponder()
). I dispositivi che supportano la misurazione della distanza NTB IEEE 802.11az eseguono la misurazione della distanza 802.11mc o 802.11az a seconda della funzionalità dell'AP, per impostazione predefinita viene utilizzata la misurazione della distanza 802.11az se l'AP supporta entrambe. I dispositivi che non supportano IEEE 802.11az eseguono tutti
gli intervalli utilizzando il protocollo IEEE 802.11mc.
Allo stesso modo, una richiesta di tipo intervallo può aggiungere un peer con connessione Wi-Fi utilizzando il proprio indirizzo MAC o il relativo PeerHandle
, utilizzando rispettivamente i metodi addWifiAwarePeer(MacAddress peer)
e addWifiAwarePeer(PeerHandle peer)
. Per ulteriori informazioni sulla rilevazione dei peer Wi-Fi Aware, consulta la documentazione di Wi-Fi Aware.
Ricerca di intervalli
Un'app emette una richiesta di misurazione della distanza utilizzando il metodo WifiRttManager.startRanging()
e fornendo quanto segue: un RangingRequest
per specificare l'operazione, un Executor
per specificare il contesto del callback e un RangingResultCallback
per ricevere i risultati.
Ad esempio:
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) { … } });
L'operazione di misurazione della distanza viene eseguita in modo asincrono e i risultati vengono
resi in uno dei callback di
RangingResultCallback
:
- Se l'intera operazione di intervallo non va a buon fine, il callback di
onRangingFailure
viene attivato con un codice di stato descritto inRangingResultCallback
. Questo tipo di errore può verificarsi se il servizio non è in grado di eseguire un'operazione di misurazione in quel momento, ad esempio perché il Wi-Fi è disattivato, perché l'applicazione ha richiesto troppe operazioni di misurazione ed è limitata o a causa di un problema di autorizzazione. - Al termine dell'operazione di misurazione della distanza, viene attivato il callback
onRangingResults
con un elenco di risultati corrispondente all'elenco di richieste, ovvero un risultato per ogni richiesta. L'ordine dei risultati non corrisponde necessariamente all'ordine delle richieste. Tieni presente che l'operazione di intervallo potrebbe essere completata, ma ogni risultato potrebbe comunque indicare un errore della misurazione specifica.
Interpreta i risultati della misurazione
Ciascuno dei risultati restituiti dal callback
onRangingResults
è specificato da un oggetto RangingResult
. Per ogni richiesta, svolgi le seguenti operazioni.
1. Identifica la richiesta
Identifica la richiesta in base alle informazioni fornite durante la creazione del
RangingRequest
:
spesso un indirizzo MAC fornito nel ScanResult
che identifica un punto di accesso. L'indirizzo MAC può essere ottenuto dal risultato della misurazione utilizzando il metodo
getMacAddress()
.
L'elenco dei risultati del rilevamento potrebbe essere in un ordine diverso rispetto ai peer (punti di accesso) specificati nella richiesta di rilevamento, pertanto devi utilizzare l'indirizzo MAC per identificare il peer, non l'ordine dei risultati.
2. Determina se ogni misurazione è andata a buon fine
Per determinare se una misurazione è andata a buon fine, utilizza il metodo
getStatus()
. Qualsiasi valore diverso da
STATUS_SUCCESS
indica un errore. Un errore significa che tutti gli altri campi di questo risultato
(ad eccezione dell'identificazione della richiesta sopra) non sono validi e che il metodo
get*
corrispondente avrà esito negativo con
un'eccezione IllegalStateException
.
3. Visualizzare i risultati di ogni misurazione riuscita
Per ogni misurazione riuscita (RangingResult
), puoi recuperare i valori
risultato con i rispettivi metodi get
:
Distanza in mm e deviazione standard della misurazione:
RSSI dei pacchetti utilizzati per le misurazioni:
Tempo in millisecondi in cui è stata eseguita la misurazione (indica il tempo dall'avvio):
Numero di misurazioni eseguite e numero di misurazioni riuscite (e su cui sono basate le misurazioni della distanza):
Tempo minimo e massimo che un dispositivo client deve attendere tra due misurazioni NTB di 11 az:
getMinTimeBetweenNtbMeasurementsMicros()
egetMaxTimeBetweenNtbMeasurementsMicros()
restituisce il tempo minimo e massimo. Se la misurazione con intervallo successivo viene richiesta prima che sia trascorso il tempo minimo, l'API restituisce il risultato dell'intervallo memorizzato nella cache. Se la misurazione di ranging successiva viene richiesta dopo il tempo massimo, l'API termina la sessione di ranging non attivata e negozia una nuova sessione di ranging con la stazione di risposta. Evita di richiedere una nuova sessione di misurazione della distanza, perché aggiunge un overhead al tempo di misurazione della distanza. Per sfruttare appieno l'efficienza della misurazione della distanza basata su trigger 802.11az, attiva la richiesta di misurazione della distanza successiva tra il tempo di misurazione minimo e massimo specificato nella misurazioneRangingResult
precedente.ripetizioni LTF (Long Training Field) utilizzate dalle stazioni di pronto intervento e iniziatore nel preambolo per il risultato dello standard IEEE 802.11az NTB:
Numero di flussi di tempo spaziale (STS) di trasmissione e ricezione che la stazione di avvio utilizzata per il risultato dello standard IEEE 802.11az NTB:
Dispositivi Android che supportano Wi-Fi-RTT
Le seguenti tabelle elencano alcuni smartphone, punti di accesso e dispositivi per negozi, magazzini e centri di distribuzione che supportano WiFi-RTT. Questi dati sono tutt'altro che esaustivi. Ti invitiamo a contattarci per elencare i tuoi prodotti compatibili con RTT qui.
Punti di accesso
Produttore e modello | Data di assistenza |
---|---|
Nest Wifi Pro (Wi-Fi 6E) | Supportato |
Compulab WILD AP | Supportato |
Google Wifi | Supportato |
Router Google Nest Wifi | Supportato |
Punto di accesso Google Nest Wifi | Supportato |
Aruba AP-635 | Supportato |
Cisco 9130 | Supportato |
Cisco 9136 | Supportato |
Cisco 9166 | Supportato |
Cisco 9164 | Supportato |
Aruba AP-505 | Supportato |
Aruba AP-515 | Supportato |
Aruba AP-575 | Supportato |
Aruba AP-518 | Supportato |
Aruba AP-505H | Supportato |
Aruba AP-565 | Supportato |
Aruba AP-535 | Supportato |
Smartphone
Produttore e modello | Versione di Android |
---|---|
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 e modelli successivi | 9.0+ |
Samsung Galaxy S20 5G | 9.0+ |
Samsung Galaxy S20 Ultra 5G | 9.0+ |
Samsung Galaxy S20 | 9.0+ |
Samsung Galaxy Note 10 o versioni successive | 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+ |
Dispositivi per negozi, magazzini e centri di distribuzione
Produttore e modello | Versione di Android |
---|---|
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 e successive |
Zebra VC8300 | 10.0+ |
Zebra EC30 | 10.0+ |
Zebra ET51 | 10.0+ |
Zebra ET56 | 10.0+ |
Zebra L10 | 10,0 e successive |
Zebra CC600/CC6000 | 10,0 e successive |
Zebra MC3300x | 10,0 e successive |
Zebra MC330x | 10.0+ |
Zebra TC52x | 10.0+ |
Zebra TC57x | 10.0+ |
Zebra EC50 (LAN e HC) | 10.0+ |
Zebra EC55 (WAN) | 10.0+ |
Zebra WT6300 | 10.0+ |
Skorpio X5 | 10.0+ |