Flutter蓝牙通信插件flutter_blue_plus的使用
Flutter蓝牙通信插件flutter_blue_plus的使用
简介
FlutterBluePlus
是一个用于Flutter的Bluetooth Low Energy (BLE) 插件,它支持大多数平台上的BLE Central角色功能。本文档将详细介绍如何在Flutter项目中使用flutter_blue_plus
进行蓝牙通信,并提供完整的示例代码。
目录
简介
FlutterBluePlus
是一个用于Flutter的Bluetooth Low Energy (BLE) 插件,它支持大多数平台上的BLE Central角色功能。如果你需要BLE Peripheral角色功能,可以考虑使用其他插件如FlutterBlePeripheral
或bluetooth_low_energy
。
准备工作
Android配置
-
更改minSdkVersion: 在
android/app/build.gradle
文件中设置minSdkVersion
为21。android { defaultConfig { minSdkVersion 21 } }
-
添加权限: 在
android/app/src/main/AndroidManifest.xml
文件中添加必要的权限。<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
-
Proguard规则: 在
project/android/app/proguard-rules.pro
文件中添加以下内容以避免发布模式下的错误。-keep class com.lib.flutter_blue_plus.* { *; }
iOS配置
在ios/Runner/Info.plist
文件中添加以下内容。
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs Bluetooth to function</string>
基本用法
错误处理
FlutterBluePlus
对错误处理非常严格,所有来自原生平台的错误都会被检查并抛出异常。
// Streams returned by FlutterBluePlus never emit any errors and never close.
var subscription = FlutterBluePlus.onScanResults.listen((results) {
if (results.isNotEmpty) {
ScanResult r = results.last;
print('${r.device.remoteId}: "${r.advertisementData.advName}" found!');
}
}, onError: (e) => print(e));
设置日志级别
FlutterBluePlus.setLogLevel(LogLevel.verbose, color: true);
蓝牙开关状态
if (await FlutterBluePlus.isSupported == false) {
print("Bluetooth not supported by this device");
return;
}
var subscription = FlutterBluePlus.adapterState.listen((state) {
print(state);
if (state == BluetoothAdapterState.on) {
// Start scanning, connecting, etc.
} else {
// Show an error to the user, etc.
}
});
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
subscription.cancel();
扫描设备
var subscription = FlutterBluePlus.onScanResults.listen((results) {
if (results.isNotEmpty) {
ScanResult r = results.last;
print('${r.device.remoteId}: "${r.advertisementData.advName}" found!');
}
}, onError: (e) => print(e));
await FlutterBluePlus.startScan(
withServices:[Guid("180D")],
withNames:["Bluno"],
timeout: Duration(seconds:15));
await FlutterBluePlus.isScanning.where((val) => val == false).first;
连接设备
var subscription = device.connectionState.listen((state) async {
if (state == BluetoothConnectionState.disconnected) {
print("${device.disconnectReason?.code} ${device.disconnectReason?.description}");
}
});
await device.connect();
await device.disconnect();
subscription.cancel();
自动连接
await device.connect(autoConnect: true, mtu: null);
await device.connectionState.where((val) => val == BluetoothConnectionState.connected).first;
await device.disconnect();
保存设备
final String remoteId = await File('/remoteId.txt').readAsString();
var device = BluetoothDevice.fromId(remoteId);
await device.connect(autoConnect: true);
MTU
final subscription = device.mtu.listen((int mtu) {
print("mtu $mtu");
});
if (Platform.isAndroid) {
await device.requestMtu(512);
}
发现服务
List<BluetoothService> services = await device.discoverServices();
services.forEach((service) {
// Do something with service
});
读取特性
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
if (c.properties.read) {
List<int> value = await c.read();
print(value);
}
}
写入特性
await c.write([0x12, 0x34]);
订阅特性
final subscription = characteristic.onValueReceived.listen((value) {
// Handle value received
});
await characteristic.setNotifyValue(true);
读取和写入描述符
var descriptors = characteristic.descriptors;
for(BluetoothDescriptor d in descriptors) {
List<int> value = await d.read();
print(value);
}
await d.write([0x12, 0x34]);
获取已连接设备
List<BluetoothDevice> devs = FlutterBluePlus.connectedDevices;
for (var d in devs) {
print(d);
}
获取系统设备
List<Guid> withServices = [Guid("180F")];
List<BluetoothDevice> devs = await FlutterBluePlus.systemDevices(withServices);
for (var d in devs) {
await d.connect();
await d.discoverServices();
}
创建绑定(仅限Android)
final bsSubscription = device.bondState.listen((value) {
print("$value prev:{$device.prevBondState}");
});
await device.createBond();
await device.removeBond();
事件API
FlutterBluePlus.events.onConnectionStateChanged.listen((event)) {
print('${event.device} ${event.connectionState}');
}
示例代码
以下是flutter_blue_plus
的完整示例代码:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
void main() {
FlutterBluePlus.setLogLevel(LogLevel.verbose, color: true);
runApp(const FlutterBlueApp());
}
class FlutterBlueApp extends StatefulWidget {
const FlutterBlueApp({Key? key}) : super(key: key);
@override
State<FlutterBlueApp> createState() => _FlutterBlueAppState();
}
class _FlutterBlueAppState extends State<FlutterBlueApp> {
BluetoothAdapterState _adapterState = BluetoothAdapterState.unknown;
late StreamSubscription<BluetoothAdapterState> _adapterStateStateSubscription;
@override
void initState() {
super.initState();
_adapterStateStateSubscription = FlutterBluePlus.adapterState.listen((state) {
_adapterState = state;
if (mounted) {
setState(() {});
}
});
}
@override
void dispose() {
_adapterStateStateSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
Widget screen = _adapterState == BluetoothAdapterState.on
? const ScanScreen()
: BluetoothOffScreen(adapterState: _adapterState);
return MaterialApp(
color: Colors.lightBlue,
home: screen,
navigatorObservers: [BluetoothAdapterStateObserver()],
);
}
}
class BluetoothAdapterStateObserver extends NavigatorObserver {
StreamSubscription<BluetoothAdapterState>? _adapterStateSubscription;
@override
void didPush(Route route, Route? previousRoute) {
super.didPush(route, previousRoute);
if (route.settings.name == '/DeviceScreen') {
_adapterStateSubscription ??= FlutterBluePlus.adapterState.listen((state) {
if (state != BluetoothAdapterState.on) {
navigator?.pop();
}
});
}
}
@override
void didPop(Route route, Route? previousRoute) {
super.didPop(route, previousRoute);
_adapterStateSubscription?.cancel();
_adapterStateSubscription = null;
}
}
通过上述代码和说明,你应该能够顺利地在Flutter项目中使用flutter_blue_plus
进行蓝牙通信。如果有任何问题或需要进一步的帮助,请参考官方文档或社区资源。
更多关于Flutter蓝牙通信插件flutter_blue_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter蓝牙通信插件flutter_blue_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 flutter_blue_plus
插件进行蓝牙通信的示例代码。这个插件是对 flutter_blue
的增强,提供了更多的功能和更好的性能。请确保你已经在 pubspec.yaml
文件中添加了 flutter_blue_plus
依赖,并且已经运行了 flutter pub get
。
1. 添加依赖
首先,在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
flutter_blue_plus: ^x.y.z # 请替换为最新版本号
2. 导入插件并初始化
在你的 Dart 文件中导入 flutter_blue_plus
插件:
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
3. 扫描和连接设备
以下是一个简单的示例,展示如何扫描蓝牙设备并连接到其中一个设备:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BluetoothScreen(),
);
}
}
class BluetoothScreen extends StatefulWidget {
@override
_BluetoothScreenState createState() => _BluetoothScreenState();
}
class _BluetoothScreenState extends State<BluetoothScreen> {
FlutterBluePlus flutterBluePlus = FlutterBluePlus.instance;
List<BluetoothDevice> devices = [];
BluetoothDevice? selectedDevice;
@override
void initState() {
super.initState();
scanForDevices();
}
Future<void> scanForDevices() async {
bool isScanning = true;
flutterBluePlus.startScan(allowDuplicates: false).listen((scanResult) {
setState(() {
devices.add(scanResult.device);
});
}).onDone(() {
if (isScanning) setState(() {}); // trigger a UI update when scanning is stopped
});
// Stop scanning after 10 seconds
Future.delayed(Duration(seconds: 10), () {
isScanning = false;
flutterBluePlus.stopScan();
});
}
Future<void> connectToDevice(BluetoothDevice device) async {
setState(() {
selectedDevice = device;
});
try {
await device.connect();
print('Connected to ${device.name}');
// Here you can discover services, characteristics, etc.
} catch (e) {
print('Failed to connect: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bluetooth Example'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: devices.length,
itemBuilder: (context, index) {
final device = devices[index];
return ListTile(
title: Text(device.name ?? 'Unknown device'),
subtitle: Text(device.id.toString()),
trailing: Icon(Icons.arrow_forward),
onTap: () => connectToDevice(device),
);
},
),
),
if (selectedDevice != null)
Text('Connected to: ${selectedDevice?.name ?? 'No Device'}'),
],
),
);
}
}
4. 发现和交互服务与特征值
一旦连接到设备,你可以发现和交互服务与特征值。以下是一个简单的示例,展示如何读取和写入特征值:
Future<void> interactWithServices(BluetoothDevice device) async {
// Discover services
List<BluetoothService> services = await device.discoverServices();
// Find a specific service (you need to know the UUID of the service you want)
BluetoothService? service = services.firstWhere(
(s) => s.uuid.toString().contains('your-service-uuid'),
orElse: () => null,
);
if (service == null) {
print('Service not found');
return;
}
// Discover characteristics of the service
List<BluetoothCharacteristic> characteristics = await service.characteristics();
// Find a specific characteristic (you need to know the UUID of the characteristic)
BluetoothCharacteristic? characteristic = characteristics.firstWhere(
(c) => c.uuid.toString().contains('your-characteristic-uuid'),
orElse: () => null,
);
if (characteristic == null) {
print('Characteristic not found');
return;
}
// Read value from characteristic
List<int> value = await characteristic.read();
print('Value read: ${bytesToHex(value)}');
// Write value to characteristic
List<int> newValue = hexToBytes('new-value-in-hex');
await characteristic.write(newValue);
print('Value written');
}
// Helper function to convert bytes to hex string
String bytesToHex(List<int> bytes) {
return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
}
// Helper function to convert hex string to bytes
List<int> hexToBytes(String hexString) {
return hexString.replaceAll(" ", "")
.split("")
.map((hex) => int.parse(hex + hex, radix: 16))
.toList();
}
5. 使用交互函数
你可以在 connectToDevice
函数中调用 interactWithServices
函数:
Future<void> connectToDevice(BluetoothDevice device) async {
setState(() {
selectedDevice = device;
});
try {
await device.connect();
print('Connected to ${device.name}');
await interactWithServices(device);
} catch (e) {
print('Failed to connect: $e');
}
}
这个示例代码展示了如何使用 flutter_blue_plus
插件扫描蓝牙设备、连接到设备,并与设备上的服务和特征值进行交互。请注意,你需要替换 'your-service-uuid'
和 'your-characteristic-uuid'
为实际设备的 UUID。