Posizione Wi-Fi: disponibile con RTT

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 con funzionalità 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 multilaterazione per stimare la posizione del dispositivo che meglio si 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 interna, il controllo vocale disambiguato (ad esempio "Accendi questa luce") e informazioni basate sulla posizione (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 dal punto di accesso; i punti di accesso non dispongono di queste informazioni. Le operazioni Wi-Fi RTT sono illimitate per le app in primo piano, ma sono limitate per le app in background.

Il Wi-Fi RTT e le funzionalità Fine-Time-Measurement (FTM) correlate 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 fare un viaggio 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 la misurazione della distanza basata su non trigger IEEE 802.11az (NTB).

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 tramite la multilaterazione con dispositivi che eseguono Android 9, devi avere accesso ai dati delle posizioni 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 del punto di accesso possono essere rappresentati come oggetti ResponderLocation, che includono latitudine, longitudine e altitudine. Per i punti di accesso 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 la procedura di misurazione.

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 i punti di accesso e determinarne le posizioni anche se non erano noti in precedenza, ad esempio quando un utente entra in un nuovo edificio.

Il supporto della misurazione 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 NTB IEEE 802.11az (indicata da WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), la tua app può trovare AP compatibili con IEEE 802.11mc e 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 della distanza, lasciando l'intervallo esatto sotto il controllo della tua app.

Requisiti

  • L'hardware del dispositivo che effettua la richiesta di misurazione deve implementare lo standard 802.11-2016 o 802.11az (misurazione non basata su trigger).
  • Il dispositivo che effettua la richiesta di misurazione deve eseguire Android 9 (livello API 28) o versioni successive. La misurazione della distanza non basata su trigger IEEE 802.11az è attivata sui dispositivi con Android 15 (livello API 35) e versioni successive.
  • Sul dispositivo che effettua la richiesta di misurazione della distanza devono essere attivi i servizi di localizzazione e la ricerca di reti Wi-Fi (in Impostazioni > Posizione).
  • Se l'app che effettua la richiesta di misurazione 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'autorizzazione ACCESS_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 IEEE 802.11-2016 FTM o lo standard IEEE 802.11az (misurazione della distanza non basata su trigger).

Configura

Per configurare l'app in modo che utilizzi Wi-Fi RTT, segui questi passaggi.

1. Richiedi autorizzazioni

Richiedi le seguenti autorizzazioni nel 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 pericolose, quindi devi richiederle al 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, vedi Richiedere le autorizzazioni app.

2. Controllare se il dispositivo supporta 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. Controllare se è disponibile il Wi-Fi RTT

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 Wi-Fi RTT se sono in uso SoftAP o il tethering. Per verificare se la funzionalità RTT Wi-Fi è disponibile, chiama isAvailable().

La disponibilità di 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 la tua app riceve l'intent di trasmissione, deve controllare lo stato attuale di disponibilità 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 ulteriori informazioni, consulta Trasmissioni.

Crea una richiesta di posizionamento

Viene creata una richiesta di misurazione (RangingRequest) specificando un elenco di AP o peer Wi-Fi Aware a cui viene richiesta una distanza. È possibile specificare più punti di accesso o peer Wi-Fi Aware in una singola richiesta di misurazione; 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 da 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 relativo oggetto ScanResult, che può essere ottenuto chiamando WifiManager.getScanResults(). Puoi utilizzare addAccessPoints(List<ScanResult>) per aggiungere più punti di accesso in batch.

Gli oggetti ScanResult possono contenere sia IEEE 802.11mc (is80211mcResponder()) sia IEEE 802.11az non-trigger based ranging (is80211azNtbResponder()) supportati dai punti di accesso. I dispositivi che supportano la misurazione IEEE 802.11az NTB eseguono la misurazione 802.11mc o 802.11az a seconda della funzionalità del punto di accesso, utilizzando per impostazione predefinita 802.11az quando il punto di accesso supporta entrambi. I dispositivi che non supportano 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 relativo indirizzo MAC o il relativo PeerHandle, utilizzando rispettivamente i metodi addWifiAwarePeer(MacAddress peer) e addWifiAwarePeer(PeerHandle peer). Per saperne di più sulla scoperta dei peer Wi-Fi Aware, consulta la documentazione di Wi-Fi Aware.

Richiesta di intervallo

Un'app invia 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 viene eseguita in modo asincrono e i risultati della misurazione vengono restituiti in uno dei callback di RangingResultCallback:

  • Se l'intera operazione di ranging non va a buon fine, viene attivato il callback onRangingFailure con un codice di stato descritto in RangingResultCallback. Questo errore può verificarsi se il servizio non riesce a 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 determinazione dell'intervallo, viene attivato il callback onRangingResults con un elenco di risultati che corrisponde 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 misurazione potrebbe essere completata, ma ogni risultato potrebbe comunque indicare un errore di quella specifica misurazione.

Interpretare i risultati della misurazione

Ciascuno dei risultati restituiti dal callback onRangingResults è specificato da un oggetto RangingResult. Per ogni richiesta, segui questi passaggi.

1. Identificare la richiesta

Identifica la richiesta in base alle informazioni fornite durante la creazione RangingRequest: il più delle volte un indirizzo MAC fornito in ScanResult che identifica un punto di accesso. L'indirizzo MAC può essere ottenuto dal risultato del ranging utilizzando il metodo getMacAddress().

L'elenco dei risultati di misurazione può essere in un ordine diverso rispetto ai peer (punti di accesso) specificati nella richiesta di misurazione, pertanto devi utilizzare l'indirizzo MAC per identificare il peer, non l'ordine dei risultati.

2. Determinare 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 e genererà un'eccezione IllegalStateException.

3. Visualizzare 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:

    getDistanceMm()

    getDistanceStdDevMm()

  • RSSI dei pacchetti utilizzati per le misurazioni:

    getRssi()

  • Ora in millisecondi in cui è stata eseguita la misurazione (indica il tempo trascorso dall'avvio):

    getRangingTimestampMillis()

  • Numero di misurazioni tentate e numero di misurazioni riuscito (e su cui si basano le misurazioni della distanza):

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • Tempo minimo e massimo che un dispositivo client deve attendere tra le misurazioni NTB 11az:

    getMinTimeBetweenNtbMeasurementsMicros() e getMaxTimeBetweenNtbMeasurementsMicros() restituiscono il tempo minimo e massimo. Se la successiva misurazione della distanza viene richiesta prima che sia trascorso il tempo minimo, l'API restituisce il risultato della misurazione della distanza memorizzato nella cache. Se la successiva misurazione della distanza viene richiesta dopo il superamento del tempo massimo, l'API termina la sessione di misurazione della distanza non attivata e negozia una nuova sessione di misurazione della distanza con la stazione di risposta. Dovresti evitare di richiedere una nuova sessione di misurazione della distanza, perché aggiunge un sovraccarico al tempo di misurazione della distanza. Per sfruttare al meglio l'efficienza di misurazione non basata su trigger di 802.11az, attiva la successiva richiesta di misurazione tra il tempo di misurazione minimo e massimo specificato nella misurazione RangingResult precedente.

  • Ripetizioni del campo di addestramento lungo (LTF) utilizzate dalle stazioni di risposta e iniziatore nel preambolo per il risultato NTB IEEE 802.11az:

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • Numero di flussi temporali spaziali (STS) di trasmissione e ricezione utilizzati dalla stazione iniziatrice per il risultato NTB IEEE 802.11az:

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Dispositivi Android che supportano Wi-Fi RTT

Le tabelle seguenti elencano alcuni smartphone, punti di accesso e dispositivi per la vendita al dettaglio, il magazzinaggio e i centri di distribuzione che supportano WiFi RTT. Questi sono tutt'altro che esaustivi. 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 Google Nest Wifi Supportato mc
Punto di accesso Google Nest Wifi 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

Smartphone

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 magazzinaggio 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+