Saltar al contenido
CrossFly es 100% open sourceSíguenos en GitHub
CrossFlyCrossFly
Empezar

Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.

Bluetooth BLE / GATT

CrossFly usa una pila BLE/GATT asíncrona (dev.crossfly.device.bluetooth), que sustituyó al antiguo JSR-82/SPP. El modelado se basa en CompletableFuture.

⚠️ Nota de honestidad (léela antes de codificar)

En el core, varias operaciones son esqueleto sobre estado en memoria — BluetoothConnectionBuilder.build() crea streams vacíos, GattCharacteristic.read()/write() solo tocan la caché local, y discoverServices() retorna una lista vacía. El transporte de radio real viene de los launchers de plataforma (Android/iOS). El modelado (UUIDs, futures, jerarquía service→characteristic→descriptor) ya es definitivo; cuenta con la API, pero prueba en dispositivo real por plataforma.

Descubrimiento y conexión

BluetoothManager bt = BluetoothManager.getInstance();   // throws IOException

// escanear (asíncrono)
bt.scanForDevices(10, TimeUnit.SECONDS, new BluetoothManager.ScanCallback() {
   public void onSuccess(List<BluetoothDevice> devices) { /* elegir uno */ }
   public void onError(String error) { Debug.log(error); }
});

// conectar (asíncrono) — devuelve una BluetoothConnection
bt.connect(device, new BluetoothManager.ConnectionCallback() {
   public void onSuccess(BluetoothConnection conn) { usar(conn); }
   public void onError(String error) { Debug.log(error); }
});

Hay variantes *Sync (scanForDevicesSync, connectSync) — úsalas solo en un worker thread, nunca en el paint thread.

GATT — leer batería y suscribir notificaciones

Modelo service → characteristic → descriptor, I/O vía CompletableFuture:

device.discoverServices(services -> {
   GattService bateria = device.getService("0000180F-0000-1000-8000-00805F9B34FB");
   GattCharacteristic nivel = bateria.getCharacteristic("00002A19-0000-1000-8000-00805F9B34FB");

   nivel.read().thenAccept(bytes -> {
      int pct = bytes[0] & 0xFF;
      Component.onUI(() -> label.setText(pct + "%"));
   });

   nivel.enableNotifications(bytes ->                     // suscribe cambios
      Component.onUI(() -> label.setText((bytes[0] & 0xFF) + "%")));
});

GattCharacteristic expone read() → CompletableFuture<byte[]>, write(byte[]) → CompletableFuture<Void>, enableNotifications(Consumer<byte[]>), y las pruebas de capacidad canRead()/canWrite()/canNotify().

BluetoothConnection es AutoCloseable

try (BluetoothConnection conn = bt.connectSync(device)) {   // solo en worker thread
   conn.write("PING".getBytes());
   byte[] resp = conn.read();
}   // se cierra por sí solo

Buenas prácticas

  • Asíncrono en la UI (connect(...)), *Sync solo en worker.
  • Los callbacks/futures vuelven a la UI con Component.onUI(...).
  • try-with-resources en la BluetoothConnection.
  • Prueba en dispositivo real por plataforma (el core es modelado; la radio vive en el launcher).

Errores comunes

  • Llamar a las variantes *Sync en el paint thread (bloquea la UI).
  • Esperar que el core haga I/O de radio real (es esqueleto; el transporte es de la plataforma).
  • Tocar la UI dentro de thenAccept/callback sin onUI(...).

Véase también

¿Te resultó útil esta página?