La comunicación de banda ultraancha es una tecnología de radio enfocada en el rango preciso (medir la ubicación con una precisión de 10 cm) entre dispositivos. Esta tecnología de radio puede usar una densidad de energía baja para mediciones de corto alcance y realizar señalización de gran ancho de banda en una gran parte del espectro de radio. El ancho de banda de UWB es superior a 500 MHz (o supera el 20% del ancho de banda fraccional).
Controlador/iniciador frente a controlado/respondedor
La comunicación UWB se produce entre dos dispositivos, uno de los cuales es un controlador y el otro es un dispositivo controlado. El controlador determina el canal complejo (UwbComplexChannel
) que compartirán los dos dispositivos y es el iniciador, mientras que el dispositivo controlado es el responsable de responder.
Un controlador puede controlar varios objetos controlados, pero un objeto controlado solo puede suscribirse a un solo controlador. Se admiten las configuraciones de controlador/iniciador y de controlado/respondedor.
Parámetros de rango
El controlador y el dispositivo controlado deben identificarse entre sí y comunicar los parámetros de rango para comenzar a establecer el rango. Este intercambio se deja a las aplicaciones para que las implementen con un mecanismo fuera de banda (OOB) seguro que elijan, como Bluetooth de bajo consumo (BLE).
Los parámetros de rango incluyen la dirección local, el canal complejo y la clave de sesión, entre otros. Ten en cuenta que estos parámetros pueden rotar o cambiar después de que finaliza la sesión de rango y deben volver a comunicarse para reiniciar el rango.
Rango en segundo plano
Una app que se ejecuta en segundo plano puede iniciar una sesión de medición de UWB si el dispositivo la admite. Para verificar las capacidades de tu dispositivo, consulta RangingCapabilities
.
La app no recibe informes de rango cuando se ejecuta en segundo plano, sino cuando pasa a primer plano.
Configuraciones de STS
La app o el servicio aprovisionan una clave de sesión para cada sesión con una secuencia de marcas de tiempo desordenadas (STS). El STS aprovisionado es más seguro que una configuración de STS estática. El STS aprovisionado es compatible con todos los dispositivos compatibles con UWB que ejecutan Android 14 o versiones posteriores.
Categoría de amenaza | STS estático | STS aprovisionado |
---|---|---|
Aire: Observador pasivo | Mitigado | Mitigado |
Aire: Ampliación de la señal | Mitigado | Mitigado |
Aire: Ataque de repetición o retransmisión | Susceptible | Mitigado |
Para STS aprovisionado:
Usa el
uwbConfigType
enRangingParameters
que admite STS aprovisionado.Proporciona la clave de 16 bytes en el campo
sessionKeyInfo
.
Para STS estáticos:
Usa el
uwbConfigType
enRangingParameters
que admite STS estáticos.Proporciona la clave de 8 bytes en el campo
sessionKeyInfo
.
Pasos
Para usar la API de UWB, sigue estos pasos:
- Asegúrate de que los dispositivos Android se ejecuten en Android 12 o versiones posteriores, y de que admitan UWB con
PackageManager#hasSystemFeature("android.hardware.uwb")
. - Si realizas mediciones de rango en dispositivos de la IoT, asegúrate de que cumplan con FiRa MAC 1.3.
- Descubre dispositivos pares compatibles con UWB con un mecanismo fuera de banda que elijas, como
BluetoothLeScanner
. - Intercambia los parámetros de rango con un mecanismo seguro fuera de banda que elijas, como
BluetoothGatt
. - Si el usuario quiere detener la sesión, cancela su alcance.
Restricciones de uso
Se aplican las siguientes restricciones al uso de la API de UWB:
- La app que inicia nuevas sesiones de medición de rango UWB debe ser una app o un servicio en primer plano, a menos que se admita el rango en segundo plano, como se ilustró anteriormente.
- Cuando la app pasa a segundo plano (mientras la sesión está en curso), es posible que ya no reciba informes de rango. Sin embargo, la sesión de UWB se seguirá manteniendo en las capas inferiores. Cuando la app vuelva al primer plano, se reanudarán los informes de rango.
Muestras de código
App de ejemplo
Para ver un ejemplo de extremo a extremo sobre cómo usar la biblioteca de Jetpack de UWB, consulta nuestra aplicación de ejemplo en GitHub. En esta app de ejemplo, se abarca la validación de la compatibilidad con UWB en un dispositivo Android, la habilitación del proceso de descubrimiento con un mecanismo fuera de banda y la configuración del rango de UWB entre dos dispositivos compatibles con UWB. En la muestra, también se incluyen casos de uso de control de dispositivos y uso compartido de contenido multimedia.
Rango de UWB
En esta muestra de código, se inicia y finaliza el rango UWB para un dispositivo controlado:
// 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()
}
}
Compatibilidad con RxJava3
La compatibilidad con RxJava3 ahora está disponible para ayudar a lograr la interoperabilidad con clientes de Java. Esta biblioteca proporciona una forma de obtener resultados de rango como un flujo Observable o Flowable, y de recuperar UwbClientSessionScope como un objeto 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();
Compatibilidad con ecosistemas
Estos son los dispositivos de socios y los SDKs de terceros compatibles.
Dispositivos móviles compatibles con UWB
A partir de enero de 2025, estos dispositivos admiten la biblioteca de Jetpack de UWB de Android:
Proveedor | Modelo del dispositivo |
---|---|
Pixel Pro (6 Pro y modelos posteriores), Fold y Tablet | |
Motorola | Edge 50 Ultra |
Samsung | Galaxy Note 20, Galaxy Plus y Ultra (S21 y modelos posteriores), Galaxy Z Fold (Fold2 y modelos posteriores) |
Nota: El rango de UWB en segundo plano es compatible con todos los dispositivos, excepto los siguientes:
- Pixel 6 Pro y Pixel 7 Pro.
- Teléfonos Samsung con Android 13 o versiones anteriores
- Teléfonos Samsung chinos con Android 14 o versiones anteriores
SDK de terceros
A partir de abril de 2023, estas soluciones de socios son compatibles con la biblioteca actual de Jetpack.
- Kit de desarrollo de UWB de Estimote
- Conocimientos sobre dispositivos móviles MK UWB Kit Mobile Edition 2.0.
Problema conocido: El orden de bytes se invierte para la dirección MAC y los campos de ID de proveedor de STS estáticos
En Android 13 y versiones anteriores, la pila de UWB de Android invierte de forma incorrecta el orden de bytes de los siguientes campos:
- Dirección MAC del dispositivo
- Dirección MAC de destino
- ID de proveedor de STS estático
La inversión del orden de bytes ocurre porque la pila de Android trata estos campos como valores, no como arrays. Estamos trabajando con FiRa para actualizar la especificación de la UCI (CR-1112) para indicar de forma explícita que estos campos deben tratarse como arrays.
Este problema se solucionará con la actualización de GMS Core en la versión 2320XXXX
.
Para cumplir con los dispositivos Android a partir de ese momento, los proveedores de IOT deben modificar tu implementación para evitar revertir el orden de bytes de estos campos.