本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。
如何扫描并连接到蓝牙设备(BLE)
目的。 发现附近的蓝牙设备,连接 到其中一个并交换数据 —— 通过流(Classic/SPP)或通过 GATT 特征(BLE:读取、写入、接收通知)。
⚠️ 诚实说明(使用前请阅读)
在
core模块 中,BLE 层是一个 基于内存缓存的骨架,而不是真正的射频:
GattCharacteristic.read()返回的是 缓存中的值(CompletableFuture.completedFuture(value)),而不是从硬件读取。GattCharacteristic.write(byte[])只是把值 保存 在本地。enableNotifications(...)注册 了监听器,但触发数据的是notifyValueChanged(...)。BluetoothDevice.discoverServices(...)在 core 中返回 空列表。真正的射频(真实的扫描/连接/GATT)由 平台启动器 (Android/iOS)提供。请将下面的代码视为 公共 API;实际行为取决于 应用运行所在的启动器。
使用的 API
BluetoothManager.getInstance() throws IOException— 单例。scanForDevices(long duration, TimeUnit unit, ScanCallback cb)— 异步发现;ScanCallback.onSuccess(List<BluetoothDevice>)/onError(String)。connect(BluetoothDevice device, ConnectionCallback cb)— 异步连接;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()。
完整示例(复制、粘贴并运行)
记住上面的诚实说明: 在
core模块中,BLE 层是一个 基于内存缓存的 骨架 —— 真正的射频来自平台启动器(Android/iOS)。下面的示例是 公共 API;实际行为取决于应用运行所在的启动器。
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
/** 可执行的主界面。将 launcher 指向此类(classname)并运行: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();
// 扫描(回调在 paint thread 之外 → 操作 UI 时用 onUI)
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"); // 蓝牙系统不可用
}
});
add(LAY_AUTO, acao);
}
}
下面的片段只展示 核心部分。要运行它,请把它放进上面的
MainWindow骨架里。
最小片段
// 已在源码验证: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) 扫描(回调在 paint thread 之外 → 操作 UI 时用 onUI)
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) 连接并通过流交换数据(Classic/SPP)
BluetoothDevice alvo = /* 由用户选择 */;
bt.connect(alvo, new BluetoothManager.ConnectionCallback() {
public void onSuccess(BluetoothConnection conn) {
try (conn) { // AutoCloseable
conn.write("PING".getBytes());
byte[] resposta = conn.read(); // 最多 4096 字节
} catch (java.io.IOException e) { /* 做相应处理 */ }
}
public void onError(String error) {
Component.onUI(() -> mostrarErro(error));
}
});
// 3) BLE / GATT — 读取并订阅某个特征的通知
GattCharacteristic ch = /* 从 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) {
// 蓝牙系统不可用
}
深入了解
- 蓝牙/BLE 指南:Bluetooth & BLE
这个页面有帮助吗?感谢你的反馈!