Puoi utilizzare la funzionalità di geolocalizzazione Wi-Fi fornita dall'API Wi-Fi RTT (Round-Trip-Time) per misurare la distanza dai punti d'accesso Wi-Fi compatibili con RTT e dai dispositivi Wi-Fi Aware peer nelle vicinanze.
Se misuri la distanza da tre o più punti di accesso, puoi utilizzare un algoritmo di multilaterazione 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 geografica dettagliati, come la navigazione indoor, il controllo vocale disambiguato (ad esempio, "Accendi questa luce") e informazioni basate sulla posizione geografica (ad esempio, "Ci sono offerte speciali per questo prodotto?").
Il dispositivo richiedente non deve connettersi ai punti di accesso per misurare la distanza con Wi-Fi RTT. Per mantenere la privacy, solo il dispositivo richiedente è in grado di determinare la distanza dall'access point; gli access point non dispongono di queste informazioni. Le operazioni Wi-Fi RTT sono illimitate per le app in primo piano, ma vengono limitate per le app in background.
Il Wi-Fi RTT e le relative funzionalità di misurazione del tempo di precisione (FTM) sono specificati dallo standard IEEE 802.11-2016. Il 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 percorso di andata e ritorno tra i dispositivi e moltiplicando questo tempo per la velocità della luce.
Android 15 (livello API 35) ha introdotto il supporto per il rilevamento della distanza non basato su trigger (NTB) IEEE 802.11az.
Differenze di implementazione in base alla versione di Android
Wi-Fi RTT è stato introdotto in Android 9 (livello API 28). Quando utilizzi questo protocollo per determinare la posizione di un dispositivo utilizzando la multilaterazione con dispositivi con Android 9, devi avere accesso ai dati sulla posizione dei punti di accesso (AP) predeterminati nella tua app. Spetta a te decidere come archiviare 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 Wi-Fi RTT che supportano le informazioni di configurazione della posizione/il report civico sulla posizione (dati LCI/LCR), il protocollo restituirà un oggetto ResponderLocation durante il processo 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. In questo modo, la tua app può trovare gli AP e determinare le loro posizioni anche se non erano noti in precedenza, ad esempio quando un utente entra in un nuovo edificio.
Il supporto del rilevamento 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à iniziatore IEEE 802.11az NTB (indicata da WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), la tua app può trovare sia gli AP compatibili con IEEE 802.11mc sia quelli compatibili 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 le misurazioni di rilevamento, lasciando l'intervallo esatto sotto il controllo della tua 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).
- Il dispositivo che effettua la richiesta di misurazione della distanza deve avere Android 9 (livello API 28) o versioni successive. Il rilevamento della distanza non basato su trigger IEEE 802.11az è abilitato sui dispositivi con Android 15 (livello API 35) e versioni successive.
- Il dispositivo che effettua la richiesta di misurazione deve avere i servizi di geolocalizzazione attivi e la ricerca di reti Wi-Fi attivata (in Impostazioni > Posizione).
- Se l'app che effettua la richiesta di rilevamento 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 disporre dell'autorizzazioneACCESS_FINE_LOCATION. - L'app deve eseguire 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 IEEE 802.11-2016 FTM o lo standard IEEE 802.11az (misurazione della distanza non basata su trigger).
Configurazione
Per configurare l'app in modo che utilizzi Wi-Fi RTT, segui questi passaggi.
1. Richiedi autorizzazioni
Richiedi le seguenti autorizzazioni nel file manifest della tua 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, pertanto devi richiederle in fase di runtime ogni volta che l'utente vuole eseguire un'operazione di scansione RTT. La tua app dovrà richiedere l'autorizzazione dell'utente se non è già stata concessa. Per ulteriori informazioni sulle autorizzazioni di runtime, consulta Richiedi autorizzazioni app.
2. Controlla se il dispositivo supporta il Wi-Fi RTT
Per verificare se il dispositivo supporta Wi-Fi RTT, utilizza l'API PackageManager:
Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
3. Verifica se il Wi-Fi RTT è disponibile
Il Wi-Fi RTT potrebbe essere presente sul dispositivo, ma potrebbe non essere disponibile perché l'utente
ha disattivato il Wi-Fi. A seconda delle funzionalità hardware e firmware, alcuni
dispositivi potrebbero non supportare il Wi-Fi RTT se sono in uso SoftAP o il tethering. Per verificare se Wi-Fi RTT è disponibile, chiama isAvailable().
La disponibilità della tecnologia Wi-Fi RTT 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 di disponibilità corrente e regolare il suo 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 saperne di più, consulta Trasmissioni.
Crea una richiesta di misurazione della distanza
Una richiesta di misurazione della distanza (RangingRequest) viene creata specificando un elenco di AP o peer Wi-Fi Aware per i quali viene richiesta una distanza. In una singola richiesta di misurazione della distanza è possibile specificare più punti di accesso o peer Wi-Fi Aware; 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 per 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 è identificato dal relativo oggetto ScanResult, che può essere ottenuto chiamando WifiManager.getScanResults().
Puoi utilizzare
addAccessPoints(List<ScanResult>)
per aggiungere più access point in un batch.
Gli oggetti ScanResult possono contenere sia AP supportati da IEEE 802.11mc (is80211mcResponder()) sia da IEEE 802.11az non-trigger based ranging (is80211azNtbResponder()). I dispositivi che supportano il rilevamento della distanza NTB IEEE 802.11az eseguono il rilevamento della distanza 802.11mc o 802.11az a seconda della funzionalità dell'AP, con l'impostazione predefinita 802.11az quando l'AP supporta entrambi. I dispositivi che non supportano lo standard IEEE 802.11az eseguono tutte le misurazioni della distanza utilizzando il protocollo IEEE 802.11mc.
Allo stesso modo, una richiesta di rilevamento può aggiungere un peer Wi-Fi Aware utilizzando il suo indirizzo MAC o il suo PeerHandle, utilizzando rispettivamente i metodi addWifiAwarePeer(MacAddress peer) e addWifiAwarePeer(PeerHandle peer). Per saperne di più sul rilevamento dei peer Wi-Fi Aware, consulta la documentazione di Wi-Fi Aware.
Richiedi il ranging
Un'app invia una richiesta di rilevamento utilizzando il metodo WifiRttManager.startRanging() e fornendo quanto segue: un RangingRequest per specificare l'operazione, un Executor per specificare il contesto di 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 rilevamento della distanza viene eseguita in modo asincrono e i risultati vengono restituiti in uno dei callback di RangingResultCallback:
- Se l'intera operazione di rilevamento della distanza non va a buon fine, viene attivato il callback
onRangingFailurecon un codice di stato descritto inRangingResultCallback. Un errore di questo tipo può verificarsi se il servizio non è in grado di eseguire un'operazione di misurazione della distanza in quel momento, ad esempio perché il Wi-Fi è disattivato, perché l'applicazione ha richiesto troppe operazioni di misurazione della distanza ed è limitata o a causa di un problema di autorizzazione. - Al termine dell'operazione di rilevamento, viene attivato il callback
onRangingResultscon un elenco di risultati che corrisponde all'elenco di richieste, un risultato per ogni richiesta. L'ordine dei risultati non corrisponde necessariamente all'ordine delle richieste. Tieni presente che l'operazione di misurazione della distanza potrebbe essere completata, ma ogni risultato potrebbe comunque indicare un errore di quella specifica misurazione.
Interpreta i risultati del ranging
Ogni risultato restituito dal callback onRangingResults è specificato da un oggetto RangingResult. Per ogni richiesta, segui questi passaggi.
1. Identifica la richiesta
Identifica la richiesta in base alle informazioni fornite durante la creazione di
RangingRequest:
molto spesso un indirizzo MAC fornito in ScanResult che identifica un punto di accesso. L'indirizzo MAC può essere ottenuto dal risultato del rilevamento della distanza utilizzando il metodo getMacAddress().
L'elenco dei risultati di misurazione della distanza potrebbe essere in un ordine diverso rispetto ai peer (punti di accesso) specificati nella richiesta di misurazione della distanza, 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 indica che tutti gli altri campi di questo risultato (ad eccezione dell'identificazione della richiesta riportata sopra) non sono validi e il metodo get* corrispondente non andrà a buon fine con un'eccezione IllegalStateException.
3. Ottenere i risultati per ogni misurazione riuscita
Per ogni misurazione riuscita (RangingResult), puoi recuperare i valori dei risultati con i rispettivi metodi get:
Distanza, in mm, e deviazione standard della misurazione:
RSSI dei pacchetti utilizzati per le misurazioni:
Ora in millisecondi in cui è stata eseguita la misurazione (che indica il tempo trascorso dall'avvio):
Numero di misurazioni tentate e numero di misurazioni riuscite (su cui si basano le misurazioni della distanza):
Tempo minimo e massimo che un dispositivo client deve attendere tra le misurazioni NTB 11az:
getMinTimeBetweenNtbMeasurementsMicros()egetMaxTimeBetweenNtbMeasurementsMicros()restituiscono l'ora minima e massima. Se la misurazione della distanza successiva viene richiesta prima che sia trascorso il tempo minimo, l'API restituisce il risultato della misurazione della distanza memorizzato nella cache. Se la misurazione del raggio successiva viene richiesta dopo il trascorrere del tempo massimo, l'API termina la sessione di misurazione del raggio non trigger e negozia una nuova sessione di misurazione del raggio con la stazione che risponde. Dovresti evitare di richiedere una nuova sessione di rilevamento, perché aggiunge overhead al tempo di misurazione del rilevamento. Per sfruttare appieno l'efficienza del rilevamento della distanza non basato su trigger 802.11az, attiva la richiesta di rilevamento della distanza successiva tra il tempo di misurazione minimo e massimo specificato nella misurazioneRangingResultprecedente.Ripetizioni del campo di addestramento lungo (LTF) utilizzate dalle stazioni di risposta e di inizializzazione nel preambolo per il risultato NTB IEEE 802.11az:
Numero di stream spaziali temporali (STS) di trasmissione e ricezione utilizzati dalla stazione di inizializzazione per il risultato NTB IEEE 802.11az:
Dispositivi Android che supportano Wi-Fi RTT
Le tabelle seguenti elencano alcuni smartphone, punti di accesso e dispositivi per la vendita al dettaglio, il magazzino e i centri di distribuzione che supportano il Wi-Fi RTT. Questi sono solo alcuni esempi. Ti invitiamo a contattarci per elencare qui i tuoi prodotti compatibili con RTT.
Punti di accesso
| Produttore e modello | Data di assistenza | Protocollo |
|---|---|---|
| Nest Wifi Pro (Wi-Fi 6E) | Supportato | mc |
| Compulab WILD AP | Supportato | mc |
| Google Wifi | Supportato | mc |
| Router Wi-Fi Google Nest | Supportato | mc |
| Punto Wi-Fi Google Nest | Supportato | mc |
| Aruba AP-635 | Supportato | mc |
| Cisco 9130 | Supportato | mc |
| Cisco 9136 | Supportato | mc |
| Cisco 9166 | Supportato | mc |
| Cisco 9164 | Supportato | mc |
| Cisco CW9172I | Supportato | mc/az |
| Cisco CW9172H | Supportato | mc/az |
| Cisco CW9176I | Supportato | mc/az |
| Cisco CW9178I | Supportato | mc/az |
| Aruba AP-505 | Supportato | mc |
| Aruba AP-515 | Supportato | mc |
| Aruba AP-575 | Supportato | mc |
| Aruba AP-518 | Supportato | mc |
| Aruba AP-505H | Supportato | mc |
| Aruba AP-565 | Supportato | mc |
| Aruba AP-535 | Supportato | mc |
| Aruba AP567 | Supportato | mc |
| Aruba AP577 | Supportato | mc |
| Aruba AP555 | Supportato | mc |
| Aruba AP635 | Supportato | mc |
| Aruba AP655 | Supportato | mc |
| Aruba AP615 | Supportato | mc |
| Aruba AP734 | Supportato | mc/az |
| Aruba AP735 | Supportato | mc/az |
| Aruba AP754 | Supportato | mc/az |
| Aruba AP755 | Supportato | mc/az |
Telefoni
| Produttore e modello | Versione di Android |
|---|---|
| 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+ |
Dispositivi per la vendita al dettaglio, il magazzino e i 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+ |
| 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 e HC) | 10.0+ |
| Zebra EC55 (WAN) | 10.0+ |
| Zebra WT6300 | 10.0+ |
| Skorpio X5 | 10.0+ |