Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar

Bluetooth BLE / GATT

O CrossFly usa uma pilha BLE/GATT assíncrona (dev.crossfly.device.bluetooth), que substituiu o antigo JSR-82/SPP. A modelagem é baseada em CompletableFuture.

⚠️ Nota de honestidade (leia antes de codar)

No core, várias operações são esqueleto sobre estado em memória — BluetoothConnectionBuilder.build() cria streams vazios, GattCharacteristic.read()/write() só tocam o cache local, e discoverServices() retorna lista vazia. O transporte de rádio real vem dos launchers de plataforma (Android/iOS). A modelagem (UUIDs, futures, hierarquia service→characteristic→descriptor) já é definitiva; conte com a API, mas teste em dispositivo real por plataforma.

Descoberta e conexão

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

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

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

Há variantes *Sync (scanForDevicesSync, connectSync) — use apenas em worker thread, nunca na paint thread.

GATT — ler bateria e assinar notificações

Modelo service → characteristic → descriptor, I/O via 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 ->                     // assina mudanças
      Component.onUI(() -> label.setText((bytes[0] & 0xFF) + "%")));
});

GattCharacteristic expõe read() → CompletableFuture<byte[]>, write(byte[]) → CompletableFuture<Void>, enableNotifications(Consumer<byte[]>), e os testes de capacidade canRead()/canWrite()/canNotify().

BluetoothConnection é AutoCloseable

try (BluetoothConnection conn = bt.connectSync(device)) {   // só em worker thread
   conn.write("PING".getBytes());
   byte[] resp = conn.read();
}   // fecha sozinho

Boas práticas

  • Assíncrono na UI (connect(...)), *Sync só em worker.
  • Callbacks/futures voltam à UI com Component.onUI(...).
  • try-with-resources na BluetoothConnection.
  • Teste em dispositivo real por plataforma (o core é modelagem; o rádio vive no launcher).

Erros comuns

  • Chamar variantes *Sync na paint thread (bloqueia a UI).
  • Esperar que o core faça I/O de rádio real (ele é esqueleto; o transporte é da plataforma).
  • Tocar a UI dentro do thenAccept/callback sem onUI(...).

Veja também

Esta página foi útil?