在移动端开发实践中,可能会要求在不同的设备之间切换,从而提升用户体验;
或者为了提升设备的利用率,实现设备之间的连接和协同工作;
不得不通过多端连接,将多个设备连接在一起,实现设备之间的数据共享、远程控制等功能,根据具体的应用场景和需求采用蓝牙的多端连接进行实现。
要实现多设备蓝牙连接需要选择使用flutter_reactive_ble或flutter_ble_lib,下面用flutter_reactive_ble作为示例。
dependencies:
flutter:
sdk: flutter
flutter_reactive_ble: ^5.2.0
final FlutterReactiveBle reactiveBle = FlutterReactiveBle();
final List<DiscoveredDevice> devices = [];
StreamSubscription<DiscoveredDevice>? scanStream;
StreamSubscription<ConnectionStateUpdate>? connectStream;
// 开始扫描
Future<void> scanDevices() async {
List<Uuid> services = [];
/**
* 过滤条件,不过滤就传空数组
* services.add(Uuid.parse("0000fff0-0000-1000-XXXX-XXXXXXXXXXX"));
* */
scanStream = reactiveBle
.scanForDevices(withServices: services, scanMode: ScanMode.lowLatency)
.listen((device) {
// 验证重复性、验证合法性才能添加进devices
devices.add(device);
}, onError: (e) {
debugPrint("onError = $e");
});
}
// 停止扫描
Future<void> stopScan() async {
scanStream?.cancel();
}
// 连接设备
Future<void> connectDevices({id}) async {
if (id == null) {
for (var device in devices) {
connectDevices(id: device.id);
}
return;
}
/**
* connectStream
* 这里可以根据实际情况使用不同的容器存储
* 如果是多端连接就需要使用HashMap去存储
* */
connectStream = reactiveBle
.connectToDevice(
id: id,
servicesWithCharacteristicsToDiscover: {},
connectionTimeout: const Duration(seconds: 3))
.listen((state) {
switch (state) {
case DeviceConnectionState.connected:
break;
case DeviceConnectionState.connecting:
break;
case DeviceConnectionState.disconnected:
break;
case DeviceConnectionState.disconnecting:
break;
}
}, onError: (e) {
debugPrint("onError = $e");
});
}
// 断开连接
Future<void> disconnectDevice() async {
connectStream?.cancel();
}
// 过滤和识别对应的服务
Future<void> discoverServices(String id) async {
reactiveBle.getDiscoveredServices(id).then((services) {
for (var service in services) {
if (service.characteristics.length < 4) {
/**
* service.deviceId
* 过滤和保存服务、特征
* service.id
* service.characteristics
* */
}
}
});
}
// 订阅特征
Future<void> listenCharacteristic(id) async {
final characteristic = QualifiedCharacteristic(
characteristicId: Uuid.parse("xxxx"),
serviceId: Uuid.parse("xxxx"),
deviceId: id);
reactiveBle.subscribeToCharacteristic(characteristic).listen((data) {
// 周期性地读取特征,可以在值发生变化时监听通知
}, onError: (e) {
debugPrint("onError = $e");
});
}
// 发送数据
Future<void> sendCharacteristic(id) async {
final characteristic = QualifiedCharacteristic(
characteristicId: Uuid.parse("xxxx"),
serviceId: Uuid.parse("xxxx"),
deviceId: id);
reactiveBle.writeCharacteristicWithoutResponse(characteristic, value: [0x00]);
}
// 读取数据
Future<void> readCharacteristic(id) async {
final characteristic = QualifiedCharacteristic(
characteristicId: Uuid.parse("xxxx"),
serviceId: Uuid.parse("xxxx"),
deviceId: id);
final respone = await reactiveBle.readCharacteristic(characteristic);
debugPrint("respone = $respone");
}
有时后为了节约电量或性能需要在设备长时间未操作时自动断开连接,这时候如果需要保持持久连接就需要像TCP类似的使用心跳包。
MTU的调整需要硬件的配合。
final mtu = await reactiveBle.requestMtu(deviceId: id, mtu: 250);
针对Android设备,可以设置连接优先级,但是当前是多端连接所以要特别谨慎。
await reactiveBle.requestConnectionPriority(deviceId: id, priority: ConnectionPriority.highPerformance);
await reactiveBle.clearGattCache(id);