La comunicazione a banda ultralarga è una tecnologia radio incentrata su misurazioni precise tra i dispositivi (misurazione della posizione con una precisione di 10 cm). Questa tecnologia radio può utilizzare una densità di energia ridotta per le misurazioni a corto raggio e eseguire la segnalazione ad alta larghezza di banda su una vasta porzione dello spettro radio. La larghezza di banda UWB è superiore a 500 MHz (o supera il 20% della larghezza di banda frazionaria).
Controller/iniziatore e controllato/rispondente
La comunicazione UWB avviene tra due dispositivi, uno dei quali è un controller e l'altro è un controllato. Il Controller determina il canale complesso
(UwbComplexChannel
) che
i due dispositivi condivideranno ed è l'iniziatore, mentre il controllato è il
risponditore.
Un controller può gestire più controllati, ma un controllato può iscriversi solo a un singolo controller. Sono supportate sia le configurazioni Controller/Initiator sia quelle Controllee/Responder.
Parametri di misurazione
Il controller e il controllato devono identificarsi e comunicare i parametri di misurazione per iniziare la misurazione. Questo scambio è lasciato alle applicazioni per essere implementato utilizzando un meccanismo out-of-band (OOB) sicuro di loro scelta, ad esempio Bluetooth Low Energy (BLE).
I parametri di intervallo includevano, tra gli altri, indirizzo locale, canale complesso e chiave di sessione. Tieni presente che questi parametri possono ruotare o cambiare in altro modo al termine della sessione di misurazione e devono essere nuovamente comunicati per riavviare la misurazione.
Rilevamento in background
Un'app in esecuzione in background può avviare una sessione di misurazione UWB se il dispositivo lo supporta. Per controllare le funzionalità del tuo dispositivo, vedi RangingCapabilities
.
L'app non riceve report di misurazione della distanza quando è in esecuzione in background, ma li riceve quando passa in primo piano.
Configurazioni STS
L'app o il servizio esegue il provisioning di una chiave di sessione per ogni sessione utilizzando una sequenza di timestamp criptata (STS). L'STS di cui è stato eseguito il provisioning è più sicuro di una configurazione STS statica. L'STS di cui è stato eseguito il provisioning è supportato su tutti i dispositivi con tecnologia UWB e con Android 14 o versioni successive.
Categoria di minaccia | STS statico | STS provisionato |
---|---|---|
Aria: osservatore passivo | Mitigati | Mitigati |
Aria: amplificazione del segnale | Mitigati | Mitigati |
Aria: attacco di replay/ritrasmissione | Suscettibile | Mitigati |
Per l'STS di cui è stato eseguito il provisioning:
Utilizza
uwbConfigType
inRangingParameters
che supporta STS di cui è stato eseguito il provisioning.Fornisci la chiave di 16 byte nel campo
sessionKeyInfo
.
Per gli STS statici:
Utilizza
uwbConfigType
inRangingParameters
che supporta STS statico.Fornisci la chiave di 8 byte nel campo
sessionKeyInfo
.
Passi
Per utilizzare l'API UWB:
- Assicurati che i dispositivi Android siano in esecuzione su Android 12 o versioni successive e che supportino la tecnologia UWB utilizzando
PackageManager#hasSystemFeature("android.hardware.uwb")
. - Se esegui la misurazione con dispositivi IoT, assicurati che siano conformi allo standard FiRa MAC 1.3.
- Individua i dispositivi peer compatibili con UWB utilizzando un meccanismo OOB a tua scelta, come
BluetoothLeScanner
. - Scambia i parametri di misurazione della distanza utilizzando un meccanismo OOB sicuro a tua scelta, come
BluetoothGatt
. - Se l'utente vuole interrompere la sessione, annullane l'ambito.
Limitazioni all'utilizzo
Le seguenti limitazioni si applicano all'utilizzo dell'API UWB:
- L'app che avvia nuove sessioni di misurazione UWB deve essere un servizio o un'app in primo piano, a meno che la misurazione in background non sia supportata come illustrato in precedenza.
- Quando l'app passa in background (mentre la sessione è in corso), l'app potrebbe non ricevere più report di misurazione della distanza. Tuttavia, la sessione UWB continuerà a essere gestita nei livelli inferiori. Quando l'app torna in primo piano, i report di misurazione del raggio di rilevamento riprendono.
Esempi di codice
App di esempio
Per un esempio end-to-end su come utilizzare la libreria Jetpack UWB, consulta la nostra applicazione di esempio su GitHub. Questa app di esempio riguarda la convalida della compatibilità UWB su un dispositivo Android, l'attivazione della procedura di rilevamento utilizzando un meccanismo OOB e la configurazione del rilevamento UWB tra due dispositivi compatibili con UWB. L'esempio illustra anche i casi d'uso di controllo del dispositivo e condivisione di contenuti multimediali.
Rilevamento UWB
Questo esempio di codice avvia e termina la misurazione della distanza UWB per un dispositivo controllato:
// The coroutineScope responsible for handling uwb ranging.
// This will be initialized when startRanging is called.
var job: Job?
// A code snippet that initiates uwb ranging for a Controlee.
suspend fun startRanging() {
// Get the ranging parameter of a partnering Controller using an OOB mechanism of choice.
val partnerAddress : Pair<UwbAddress, UwbComplexChannel> = listenForPartnersAddress()
// Create the ranging parameters.
val partnerParameters = RangingParameters(
uwbConfigType = UwbRangingParameters.UWB_CONFIG_ID_1,
// SessionKeyInfo is used to encrypt the ranging session.
sessionKeyInfo = null,
complexChannel = partnerAddress.second,
peerDevices = listOf(UwbDevice.createForAddress(partnerAddress.first)),
updateRateType = UwbRangingParameters.RANGING_UPDATE_RATE_AUTOMATIC
)
// Initiate a session that will be valid for a single ranging session.
val clientSession = uwbManager.clientSessionScope()
// Share the localAddress of the current session to the partner device.
broadcastMyParameters(clientSession.localAddress)
val sessionFlow = clientSession.prepareSession(partnerParameters)
// Start a coroutine scope that initiates ranging.
CoroutineScope(Dispatchers.Main.immediate).launch {
sessionFlow.collect {
when(it) {
is RangingResultPosition -> doSomethingWithPosition(it.position)
is RangingResultPeerDisconnected -> peerDisconnected(it)
}
}
}
}
// A code snippet that cancels uwb ranging.
fun cancelRanging() {
// Canceling the CoroutineScope will stop the ranging.
job?.let {
it.cancel()
}
}
Supporto di RxJava3
Il supporto di Rxjava3 è ora disponibile per contribuire a realizzare l'interoperabilità con i client Java. Questa libreria fornisce un modo per ottenere risultati di ricerca come stream Observable o Flowable e per recuperare UwbClientSessionScope come oggetto Single.
private final UwbManager uwbManager;
// Retrieve uwbManager.clientSessionScope as a Single object
Single<UwbClientSessionScope> clientSessionScopeSingle =
UwbManagerRx.clientSessionScopeSingle(uwbManager);
UwbClientSessionScope uwbClientSessionScope = clientSessionScopeSingle.blockingGet();
// Retrieve uwbClientSessionScope.prepareSession Flow as an Observable object
Observable<RangingResult> rangingResultObservable =
UwbClientSessionScopeRx.rangingResultsObservable(clientSessionScope,
rangingParameters);
// Consume ranging results from Observable
rangingResultObservable.subscribe(
rangingResult -> doSomethingWithRangingResult(result), // onNext
(error) -> doSomethingWithError(error), // onError
() -> doSomethingOnResultEventsCompleted(), //onCompleted
);
// Unsubscribe
rangingResultObservable.unsubscribe();
// Retrieve uwbClientSessionScope.prepareSession Flow as a Flowable object
Flowable<RangingResult> rangingResultFlowable =
UwbClientSessionScopeRx.rangingResultsFlowable(clientSessionScope,
rangingParameters);
// Consume ranging results from Flowable using Disposable
Disposable disposable = rangingResultFlowable
.delay(1, TimeUnit.SECONDS)
.subscribeWith(new DisposableSubscriber<RangingResult> () {
@Override public void onStart() {
request(1);
}
@Override public void onNext(RangingResult rangingResult) {
doSomethingWithRangingResult(rangingResult);
request(1);
}
@Override public void onError(Throwable t) {
t.printStackTrace();
}
@Override public void onComplete() {
doSomethingOnEventsCompleted();
}
});
// Stop subscription
disposable.dispose();
Supporto dell'ecosistema
Di seguito sono riportati i dispositivi partner e gli SDK di terze parti supportati.
Dispositivi mobili compatibili con UWB
A partire da gennaio 2025, questi dispositivi supportano la libreria Jetpack UWB di Android:
Fornitore | Modello del dispositivo |
---|---|
Pixel Pro (6 Pro e modelli successivi), Fold, Tablet | |
Motorola | Edge 50 Ultra |
Samsung | Galaxy Note 20, Galaxy Plus e Ultra (S21 e modelli successivi), Galaxy Z Fold (Fold2 e modelli successivi) |
Nota: la misurazione UWB in background è supportata su tutti i dispositivi, ad eccezione dei seguenti:
- Pixel 6 Pro e Pixel 7 Pro.
- Smartphone Samsung con Android 13 o versioni precedenti.
- Smartphone Samsung cinesi con Android 14 o versioni precedenti.
SDK di terze parti
Da aprile 2023, queste soluzioni partner sono compatibili con la libreria Jetpack attuale.
- Kit di sviluppo UWB di Estimote.
- Mobile Knowledge MK UWB Kit Mobile Edition 2.0.
Problema noto: ordine dei byte invertito per i campi dell'indirizzo MAC e dell'ID fornitore STS statico
Su Android 13 e versioni precedenti, lo stack UWB di Android inverte erroneamente l'ordine dei byte per i seguenti campi:
- Indirizzo MAC del dispositivo
- Indirizzo MAC di destinazione
- ID fornitore STS statico
L'inversione dell'ordine dei byte si verifica perché lo stack di Android tratta questi campi come valori, non come array. Stiamo collaborando con FiRa per aggiornare la specifica UCI (CR-1112) in modo da indicare esplicitamente che questi campi devono essere trattati come array.
Questo problema verrà risolto tramite l'aggiornamento di GMS Core nella release 2320XXXX
.
Per essere conformi ai dispositivi Android da quel momento in poi, i fornitori di IoT devono modificare la tua implementazione per evitare di invertire l'ordine dei byte di questi campi.