Android 16 introduce il modulo Ranging, che fornisce un'interfaccia unificata e standardizzata per la misurazione precisa della distanza tra i dispositivi. Puoi utilizzare questa API per misurare la distanza e la posizione dei dispositivi peer senza dover gestire singolarmente ogni tecnologia di misurazione della distanza.
Il modulo Ranging supporta le seguenti tecnologie:
- Ultra-wideband
- Suono del canale Bluetooth
- Wi-Fi NAN RTT
- Rilevamento della distanza RSSI Bluetooth
Funzionalità e disponibilità di misurazione
La classe RangingManager fornisce alle app informazioni sulle tecnologie di misurazione della distanza supportate dal dispositivo locale, nonché sulla disponibilità e sulle funzionalità di ciascuna tecnologia. Le app possono registrarsi per un Callback per
ricevere aggiornamenti su eventuali modifiche alla disponibilità o alle funzionalità di
qualsiasi tecnologia supportata.
Ruoli dispositivo
Un dispositivo che partecipa a una sessione di misurazione deve essere un iniziatore o un
risponditore. Il dispositivo iniziatore avvia la sessione di misurazione della distanza con uno o più
dispositivi di risposta. Un dispositivo di risposta risponde alle richieste di misurazione della distanza di un solo
iniziatore alla volta. Puoi specificare il ruolo per un determinato dispositivo in una sessione di misurazione
con la classe RangingPreference.
Tipi di sessione di determinazione della distanza
Quando si avvia una sessione di misurazione della distanza tra dispositivi, spesso è necessario stabilire un trasporto di dati fuori banda (OOB) per scambiare i parametri della sessione.
Il modulo Ranging può gestire le negoziazioni OOB per te, ma supporta anche implementazioni OOB personalizzate.
Implementazione OOB predefinita
In questo tipo di sessione (RANGING_SESSION_OOB), il modulo Ranging gestisce
le negoziazioni OOB per avviare una sessione di ranging. Seleziona i parametri adatti
in base alle preferenze di misurazione fornite dall'app e utilizza le
tecnologie appropriate in base a ciò che supportano entrambi i dispositivi. Questo tipo di sessione
utilizza un OOB specification standardizzato.
Il modulo Ranging definisce solo il formato e la sequenza dei dati OOB da utilizzare per interagire con un dispositivo peer. Non gestisce l'individuazione o la connessione dei dispositivi peer.
Implementazione OOB personalizzata
In questo tipo di sessione (RANGING_SESSION_RAW), l'app bypassa il flusso OOB del modulo Ranging e gestisce i propri parametri e la propria negoziazione OOB. Ciò significa che
l'app deve determinare quali tecnologie supporta il dispositivo peer, negoziare
i parametri di ranging e avviare la sessione di ranging.
Preferenze di misurazione
Utilizza un oggetto RangingPreference per specificare i parametri selezionati per una sessione di
misurazione. È incluso quanto segue:
- Ruolo del dispositivo. Indica se il dispositivo sarà l'iniziatore o il risponditore.
- Configurazione della misurazione della distanza. Un oggetto
RangingConfigspecifica il tipo di sessione di rilevamento e altri parametri necessari per avviare una sessione di rilevamento. - Configurazione sessione. Un oggetto
SessionConfigspecifica i parametri da applicare alla sessione di misurazione, ad esempio il limite di misurazione, la fusione dei sensori, la configurazione del recinto virtuale e altro ancora.
Autorizzazione di raggruppamento
Il modulo Ranging richiede una nuova autorizzazione unificata
(android.permission.RANGING) per accedere a tutte le tecnologie di ranging
attuali e future. Questa autorizzazione è presente nell'elenco NEARBY_DEVICES_PERMISSIONS.
<uses-permission android:name="android.permission.RANGING" />
Limitazioni e restrizioni
Il modulo Ranging potrebbe limitare il ranging per diversi motivi, tra cui:
- Le app di terze parti possono eseguire la misurazione in background solo con l'ultra-wideband e solo sui dispositivi supportati. La misurazione in background con altre tecnologie non è consentita.
- Il rilevamento non è consentito quando è stato raggiunto il numero massimo di sessioni di rilevamento simultanee per dispositivo.
- La misurazione potrebbe essere limitata a causa di problemi di integrità del sistema, come batteria, prestazioni o memoria.
Il modulo Ranging presenta anche le seguenti limitazioni note:
- Il modulo Ranging supporta solo la trasmissione di dati di misurazione ai dispositivi peer per l'ultra-wideband. Per le altre tecnologie, il modulo Ranging fornisce i dati di misurazione della distanza solo al dispositivo iniziatore.
- Il modulo Ranging supporta solo l'aggiunta dinamica di dispositivi in modalità di misurazione grezza e solo per l'ultra-wideband.
- Il modulo Ranging non supporta sessioni ultra-wideband uno-a-molti per le implementazioni OOB predefinite. Se trasmetti più handle di dispositivi, il modulo crea una sessione one-to-one per ogni dispositivo peer che supporta l'ultra-wideband.
Eseguire una sessione di misurazione
Per eseguire una sessione di misurazione utilizzando il modulo Ranging:
- Verifica che tutti i dispositivi utilizzino Android 16 o versioni successive.
- Richiedi l'autorizzazione
android.permission.RANGINGnel manifest dell'app. - Valuta le funzionalità e la disponibilità delle tecnologie di misurazione della distanza.
- Scopri un dispositivo peer per le operazioni di misurazione.
- Stabilisci una connessione per uno scambio fuori banda utilizzando uno dei tipi di sessione descritti in Tipi di sessione di ranging.
- Avvia la misurazione e acquisisci continuamente i dati di misurazione.
- Termina la sessione di misurazione.
Il seguente esempio di codice mostra questi passaggi sia per il ruolo di iniziatore sia per il ruolo di rispondente.
Kotlin
class RangingApp {
// Starts a ranging session on the initiator side.
fun startRangingInitiator(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
val config = OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build()
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build()
// Start ranging session.
session.start(preference)
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop()
}
// Starts a ranging session on the responder side.
fun startRangingResponder(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
val config = OobResponderRangingConfig.Builder(deviceHandle).build()
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build()
// Start the ranging session.
session.start(preference)
// Stop the ranging session
session.stop()
}
}
Java
public class RangingApp {
// Starts a ranging session on the initiator side.
void startRangingInitiator(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
OobInitiatorRangingConfig config = new OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build();
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build();
// Start ranging session.
session.start(preference);
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop();
}
// Starts a ranging session on the responder side.
void startRangingResponder(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
OobResponderRangingConfig config = new OobResponderRangingConfig.Builder( deviceHandle).build();
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build();
// Start the ranging session.
session.start(preference);
// Stop the ranging session
session.stop();
}
}
Interoperabilità UWB con i dispositivi iOS
Il modulo Ranging supporta l'interoperabilità con i dispositivi iOS utilizzando la banda ultralarga (UWB). Per eseguire la misurazione della distanza con un dispositivo iOS, devi utilizzare un'implementazione OOB personalizzata e configurare la sessione di misurazione della distanza con parametri specifici che corrispondono al protocollo per accessori Apple Nearby Interaction. Fai riferimento all'app di esempio.
Quando crei RangingPreference, utilizza RawRangingDevice e
UwbRangingParams per specificare la configurazione. I seguenti parametri sono
fondamentali per l'interoperabilità con iOS:
- ID configurazione:utilizza
UwbRangingParams.CONFIG_UNICAST_DS_TWR. - Session Key Info:fornisci un array di byte contenente l'ID fornitore e l'IV STS statico.
- Canale complesso:imposta il numero del canale e l'indice del preambolo in modo che corrispondano alla configurazione del dispositivo iOS.
Il seguente snippet di codice mostra come creare un RangingPreference per
un dispositivo iniziatore che esegue la misurazione della distanza con un responder iOS:
Kotlin
// Create UwbRangingParams with iOS-specific configuration
val uwbRangingParams = UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress
)
.setComplexChannel(
UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build()
)
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build()
// Create RawRangingDevice
val rawRangingDevice = RawRangingDevice.Builder()
.setRangingDevice(RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build()
// Create SessionConfig
val sessionConfig = SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build()
// Create RangingPreference for the initiator
val preference = RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build()
)
.setSessionConfig(sessionConfig)
.build()
Java
// Create UwbRangingParams with iOS-specific configuration
UwbRangingParams uwbRangingParams = new UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress)
.setComplexChannel(new UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build())
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build();
// Create RawRangingDevice
RawRangingDevice rawRangingDevice = new RawRangingDevice.Builder()
.setRangingDevice(new RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build();
// Create SessionConfig
SessionConfig sessionConfig = new SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(new DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build();
// Create RangingPreference for the initiator
RangingPreference preference = new RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
new RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build())
.setSessionConfig(sessionConfig)
.build();
App di esempio
Per un esempio end-to-end di come utilizzare il modulo Ranging, consulta l'app di esempio in AOSP. Questa app di esempio copre tutte le tecnologie di misurazione supportate dal modulo Ranging e include flussi per entrambi i tipi di sessione supportati.
Interoperabilità UWB con i dispositivi iOS
L'app di esempio per Android supporta l'avvio di una sessione di misurazione UWB con l'app di esempio per iOS.