Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.
Cómo escanear y conectar a un dispositivo Bluetooth (BLE)
Propósito. Descubrir dispositivos Bluetooth cercanos, conectar a uno de ellos e intercambiar datos — por stream (Classic/SPP) o por características GATT (BLE: leer, escribir, recibir notificaciones).
⚠️ Nota de honestidad (léela antes de usar)
En el módulo
core, la capa BLE es un esqueleto sobre caché en memoria, no la radio real:
GattCharacteristic.read()devuelve el valor en caché (CompletableFuture.completedFuture(value)), no una lectura del hardware.GattCharacteristic.write(byte[])solo guarda el valor localmente.enableNotifications(...)registra el listener, pero quien dispara los datos esnotifyValueChanged(...).BluetoothDevice.discoverServices(...)devuelve lista vacía en el core.La radio real (scan/conexión/GATT de verdad) la proveen los launchers de plataforma (Android/iOS). Trata el código de abajo como la API pública; el comportamiento efectivo depende del launcher en el que se ejecute la aplicación.
APIs usadas
BluetoothManager.getInstance() throws IOException— singleton.scanForDevices(long duration, TimeUnit unit, ScanCallback cb)— descubrimiento asíncrono;ScanCallback.onSuccess(List<BluetoothDevice>)/onError(String).connect(BluetoothDevice device, ConnectionCallback cb)— conexión asíncrona;ConnectionCallback.onSuccess(BluetoothConnection)/onError(String).BluetoothConnection(AutoCloseable) —read()/read(int max)→byte[];write(byte[])/write(String)→int.- GATT:
GattCharacteristic.read()→CompletableFuture<byte[]>;write(byte[])→CompletableFuture<Void>;enableNotifications(Consumer<byte[]>)→CompletableFuture<Void>. BluetoothManager.isBluetoothEnabled(),getPairedDevices(...),getLocalDevice().
Ejemplo completo (copiar, pegar y ejecutar)
Recuerda la nota de honestidad de arriba: en el módulo
corela capa BLE es un esqueleto sobre caché en memoria — la radio real viene de los launchers de plataforma (Android/iOS). El ejemplo de abajo es la API pública; el comportamiento efectivo depende del launcher en el que se ejecute la aplicación.
package com.exemplo;
import java.util.concurrent.*; // TimeUnit
import dev.crossfly.ui.*; // Window, Component, Button, Label
import dev.crossfly.ui.layout.*; // VerticalLayout
import dev.crossfly.device.bluetooth.*; // BluetoothManager, BluetoothDevice
/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
Label resultado = new Label("");
add(LAY_AUTO, resultado);
Button acao = new Button("Escanear Bluetooth");
acao.onAction(c ->
{
try
{
BluetoothManager bt = BluetoothManager.getInstance();
// Escanear (callbacks fuera de la paint thread → onUI al tocar la UI)
bt.scanForDevices(10, TimeUnit.SECONDS, new BluetoothManager.ScanCallback()
{
public void onSuccess(java.util.List<BluetoothDevice> devices)
{
Component.onUI(() -> resultado.setText("Encontrados: " + devices.size()));
}
public void onError(String error)
{
Component.onUI(() -> resultado.setText("Erro: " + error));
}
});
}
catch (java.io.IOException e)
{
resultado.setText("Bluetooth indisponível"); // sistema Bluetooth no disponible
}
});
add(LAY_AUTO, acao);
}
}
El fragmento de abajo muestra solo el núcleo. Para ejecutarlo, colócalo en el esqueleto
MainWindowde arriba.
Fragmento mínimo
// verificado en la fuente: BluetoothManager.java (getInstance, scanForDevices, connect); BluetoothConnection.java (read/write); GattCharacteristic.java (read/write/enableNotifications)
import java.util.concurrent.*; // TimeUnit
import dev.crossfly.device.bluetooth.*; // BluetoothManager, BluetoothDevice, BluetoothConnection, GattCharacteristic
import dev.crossfly.ui.*; // Component (onUI)
try {
BluetoothManager bt = BluetoothManager.getInstance();
// 1) Escanear (callbacks fuera de la paint thread → onUI al tocar la UI)
bt.scanForDevices(10, TimeUnit.SECONDS, new BluetoothManager.ScanCallback() {
public void onSuccess(java.util.List<BluetoothDevice> devices) {
Component.onUI(() -> listarDispositivos(devices));
}
public void onError(String error) {
Component.onUI(() -> mostrarErro(error));
}
});
// 2) Conectar e intercambiar datos por stream (Classic/SPP)
BluetoothDevice alvo = /* elegido por el usuario */;
bt.connect(alvo, new BluetoothManager.ConnectionCallback() {
public void onSuccess(BluetoothConnection conn) {
try (conn) { // AutoCloseable
conn.write("PING".getBytes());
byte[] resposta = conn.read(); // hasta 4096 bytes
} catch (java.io.IOException e) { /* maneja */ }
}
public void onError(String error) {
Component.onUI(() -> mostrarErro(error));
}
});
// 3) BLE / GATT — leer y suscribir notificaciones de una característica
GattCharacteristic ch = /* obtenida del servicio del device */;
ch.enableNotifications(data ->
Component.onUI(() -> atualizarValor(data))); // Consumer<byte[]>
ch.read().thenAccept(valor ->
Component.onUI(() -> mostrarValor(valor))); // CompletableFuture<byte[]>
} catch (java.io.IOException e) {
// sistema Bluetooth no disponible
}
Profundiza
- Guía de Bluetooth/BLE: Bluetooth & BLE