Puoi utilizzare la funzionalità di localizzazione Wi-Fi fornita dall'API Wi-Fi RTT (Round-Trip-Time) per misurare la distanza dai punti di accesso Wi-Fi compatibili con RTT nelle vicinanze e dai dispositivi Wi-Fi Aware peer.
Se misuri la distanza da tre o più punti di accesso, puoi utilizzare un algoritmo multilaterale per stimare la posizione del dispositivo più adatta a queste misurazioni. In genere il risultato è preciso entro 1-2 metri.
Con questa precisione, puoi sviluppare servizi basati sulla posizione geografica dettagliati, come la navigazione all'interno, il controllo vocale disambigua (ad es. "Accendi questa luce") e 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 garantire la privacy, solo il dispositivo richiedente è in grado di determinare la distanza dal punto di accesso; i punti di accesso non hanno queste informazioni. Le operazioni RTT Wi-Fi sono illimitate per le app in primo piano, ma sono limitate per le app in background.
RTT Wi-Fi e le relative funzionalità di misurazione fine (FTM) sono specificate 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 round trip tra i dispositivi e moltiplicando il tempo per la velocità della luce.
Differenze di implementazione in base alla versione di Android
Il 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 a dati sulle posizioni dei punti di accesso (AP) predeterminati nella tua app. Sta a te decidere come archiviare e recuperare questi dati.
Sui dispositivi con Android 10 (livello API 29) e versioni successive, i dati sulla posizione AP possono essere
rappresentati come oggetti
ResponderLocation
,
tra cui latitudine, longitudine e altitudine. Per gli AP Wi-Fi che supportano le informazioni sulla configurazione della posizione/il report civico sulla posizione (dati LCI/LCR), il protocollo restituirà un oggetto ResponderLocation
durante il processo di vario tipo.
Questa funzionalità consente alle app di interrogare gli 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.
Requisiti
- L'hardware del dispositivo che effettua la richiesta di portata deve implementare lo standard FTM 802.11-2016.
- Sul dispositivo che effettua la richiesta di portata deve essere installato Android 9 (livello API 28) o versioni successive.
- Sul dispositivo che effettua la richiesta di portata 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 intervallo 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 query sull'intervallo di punti di accesso mentre è visibile o in un servizio in primo piano. L'app non può accedere alle informazioni sulla posizione in background.
- Il punto di accesso deve implementare lo standard FTM IEEE 802.11-2016.
Configura
Per configurare l'app per l'utilizzo di Wi-Fi RTT, svolgi i passaggi che seguono.
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. La tua app dovrà richiedere l'autorizzazione
dell'utente, se non è già stata concessa. Per ulteriori informazioni sulle autorizzazioni di runtime, consulta Richiedere le autorizzazioni app.
2. Controlla se il dispositivo supporta la funzionalità 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. Verificare se la funzionalità RTT Wi-Fi è disponibile
Il dispositivo potrebbe disporre di RTT Wi-Fi, che però potrebbe non essere attualmente disponibile perché l'utente ha disattivato il Wi-Fi. In base alle funzionalità hardware e firmware di alcuni dispositivi, alcuni dispositivi potrebbero non supportare la funzionalità Wi-Fi RTT se sono in uso le funzionalità SoftAP o il tethering. Per verificare se la funzionalità RTT Wi-Fi è attualmente disponibile, chiama isAvailable().
La disponibilità della funzionalità RTT Wi-Fi può variare 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 la tua app riceve l'intent di trasmissione, deve controllare lo stato di disponibilità attuale e modificare il proprio comportamento di conseguenza.
Ecco alcuni esempi:
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, vedi Trasmissioni.
Crea una richiesta con intervallo
Una richiesta di intervallo (RangingRequest) viene creata specificando un elenco di punti di accesso o peer Wi-Fi Aware a cui viene richiesto un intervallo. È possibile specificare più punti di accesso o peer Wi-Fi Aware in una singola richiesta di portata; vengono misurate e restituite le distanze da tutti i dispositivi.
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 è identificato dal suo oggetto ScanResult, che può essere ottenuto chiamando WifiManager.getScanResults(). Puoi utilizzare addAccessPoints(List
Allo stesso modo, una richiesta di tipo intervallo può aggiungere un peer Wi-Fi Aware utilizzando il proprio indirizzo MAC o il proprio PeerHandle, utilizzando rispettivamente i metodi addWifiAwarePeer(MacAddress peer) e addWifiAwarePeer(PeerHandle peer). Per ulteriori informazioni sul rilevamento di peer Wi-Fi Aware, consulta la documentazione relativa a Wi-Fi Aware.
Intervallo di richiesta
Un'app emette una richiesta di tipo mediante il metodo WifiRttManager.startRanging() e fornisce quanto segue: una RangingRequest per specificare l'operazione, un Executor per specificare il contesto del callback e un RangingResultCallback per ricevere i risultati.
Ecco alcuni esempi:
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 intervallo viene eseguita in modo asincrono e i risultati di intervallo vengono restituiti in uno dei callback di RangingResultCallback:
- Se l'intera operazione di intervallo non va a buon fine, il callback onRangingFailure viene attivato con un codice di stato descritto in RangingResultCallback. Un errore di questo tipo può verificarsi se al momento il servizio non può eseguire un'operazione di portata, ad esempio perché il Wi-Fi è disabilitato, perché l'applicazione ha richiesto troppe operazioni di portata ed è limitata o a causa di un problema di autorizzazione.
- Al termine dell'operazione di intervallo, il callback onRangingResults viene attivato con un elenco di risultati che corrisponde all'elenco di richieste, un risultato per ogni richiesta. L'ordine dei risultati non necessariamente corrisponde 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 con intervallo
Ciascuno dei risultati restituiti dal callback onRangingResults è specificato da un oggetto RangingResult. Per ogni richiesta, procedi nel seguente modo.
1. Identifica la richiesta
Identifica la richiesta in base alle informazioni fornite durante la creazione della
RangingRequest:
molto spesso un indirizzo MAC fornito in ScanResult
che identifica un
punto di accesso. L'indirizzo MAC può essere ottenuto dal risultato che indica la distanza utilizzando il metodo getMacAddress().
L'elenco dei risultati di rilevamento potrebbe essere in un ordine diverso rispetto ai peer (punti di accesso) specificati nella richiesta, quindi devi utilizzare l'indirizzo MAC per identificare il peer, non l'ordine dei risultati.
2. Determinare se ogni misurazione è riuscita
Per determinare se una misurazione è riuscita, 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 non andrà a buon fine con un'eccezione
LegalStateException .
3. Ottieni risultati per ogni misurazione riuscita
Per ogni misurazione riuscita, puoi recuperare i valori dei risultati con i
rispettivi metodi get
:
Distanza in mm e deviazione standard della misura:
RSSI dei pacchetti utilizzati per le misurazioni:
Tempo in millisecondi in cui è stata effettuata la misurazione (che indica il tempo dall'avvio):
Numero di misurazioni eseguite e numero di misurazioni riuscite (e su cui sono basate le misurazioni della distanza):
Dispositivi Android che supportano Wi-Fi-RTT
Le tabelle riportate di seguito elencano alcuni telefoni, punti di accesso e dispositivi per vendita al dettaglio, magazzini e centri di distribuzione che supportano Wi-Fi-RTT. Sono tutt'altro che esaustivi. Ti invitiamo a contattarci per elencare i tuoi prodotti che supportano RTT.
Punti di accesso
Produttore e modello | Data assistenza |
---|---|
Nest Wifi Pro (Wi-Fi 6E) | Prove di supporto |
Compulab WILD AP | Prove di supporto |
Google Wifi | Prove di supporto |
Router Wi-Fi Google Nest | Prove di supporto |
Punto di accesso Google Nest | Prove di supporto |
Aruba AP-635 | Prove di supporto |
Cisco 9130 | Prove di supporto |
Cisco 9136 | Prove di supporto |
Cisco 9166 | Prove di supporto |
Cisco 9164 | Prove di supporto |
Aruba AP-505 | Prove di supporto |
Aruba AP-515 | Prove di supporto |
Aruba AP-575 | Prove di supporto |
Aruba AP-518 | Prove di supporto |
Aruba AP-505H | Prove di supporto |
Aruba AP-565 | Prove di supporto |
Aruba AP-535 | Prove di supporto |
Smartphone
Produttore e modello | Versione di Android |
---|---|
Pixel 6 | 9,0 e oltre |
Pixel 6 Pro | 9,0 e oltre |
Pixel 5 | 9,0 e oltre |
Pixel 5a | 9,0 e oltre |
Pixel 5a (5G) | 9,0 e oltre |
Xiaomi Mi 10 Pro | 9,0 e oltre |
Xiaomi Mi 10 | 9,0 e oltre |
Xiaomi Redmi Mi 9T Pro | 9,0 e oltre |
Xiaomi Mi 9T | 9,0 e oltre |
Xiaomi Mi 9 | 9,0 e oltre |
Xiaomi Mi Note 10 | 9,0 e oltre |
Xiaomi Mi Note 10 Lite | 9,0 e oltre |
Xiaomi Redmi Note 9S | 9,0 e oltre |
Xiaomi Redmi Note 9 Pro | 9,0 e oltre |
Xiaomi Redmi Note 8T | 9,0 e oltre |
Xiaomi Redmi Note 8 | 9,0 e oltre |
Xiaomi Redmi K30 Pro | 9,0 e oltre |
Xiaomi Redmi K20 Pro | 9,0 e oltre |
Xiaomi Redmi K20e | 9,0 e oltre |
Xiaomi Redmi Note 5 Pro | 9,0 e oltre |
Xiaomi Mi CC9 Pro | 9,0 e oltre |
LG G8X ThinQ | 9,0 e oltre |
LG V50S ThinQ | 9,0 e oltre |
LG V60 ThinQ | 9,0 e oltre |
LG V30 | 9,0 e oltre |
Samsung Galaxy Note 10+ 5G | 9,0 e oltre |
Samsung Galaxy S20 e modelli successivi (5G) | 9,0 e oltre |
Samsung Galaxy S20 e modelli successivi | 9,0 e oltre |
Samsung Galaxy S20 (5G) | 9,0 e oltre |
Samsung Galaxy S20 Ultra 5G | 9,0 e oltre |
Samsung Galaxy S20 | 9,0 e oltre |
Samsung Galaxy Note 10 o versioni successive | 9,0 e oltre |
Samsung Galaxy Note 10 (5G) | 9,0 e oltre |
Samsung Galaxy Note 10 | 9,0 e oltre |
Samsung A9 Pro | 9,0 e oltre |
Google Pixel 4 XL | 9,0 e oltre |
Google Pixel 4 | 9,0 e oltre |
Google Pixel 4a | 9,0 e oltre |
Google Pixel 3 XL | 9,0 e oltre |
Google Pixel 3 | 9,0 e oltre |
Google Pixel 3a XL | 9,0 e oltre |
Google Pixel 3a | 9,0 e oltre |
Google Pixel 2 XL | 9,0 e oltre |
Google Pixel 2 | 9,0 e oltre |
Google Pixel 1 XL | 9,0 e oltre |
Google Pixel 1a | 9,0 e oltre |
Poco X2 | 9,0 e oltre |
Sharp Aquos R3 SH-04L | 9,0 e oltre |
Dispositivi per negozi, magazzini e centri di distribuzione
Produttore e modello | Versione di Android |
---|---|
Zebra PS20 | 10,0 e successive |
Zebra TC52/TC52HC | 10,0 e successive |
Zebra TC57 | 10,0 e successive |
Zebra TC72 | 10,0 e successive |
Zebra TC77 | 10,0 e successive |
Zebra MC93 | 10,0 e successive |
Zebra TC8300 | 10,0 e successive |
Zebra VC8300 | 10,0 e successive |
Zebra EC30 | 10,0 e successive |
Zebra ET51 | 10,0 e successive |
Zebra ET56 | 10,0 e successive |
Zebra L10 | 10,0 e successive |
Zebra CC600/CC6000 | 10,0 e successive |
Zebra MC3300x | 10,0 e successive |
Zebra MC330x | 10,0 e successive |
Zebra TC52x | 10,0 e successive |
Zebra TC57x | 10,0 e successive |
Zebra EC50 (LAN e HC) | 10,0 e successive |
Zebra EC55 (WAN) | 10,0 e successive |
Zebra WT6300 | 10,0 e successive |
Skorpio X5 | 10,0 e successive |