前言
在生活中,使用到蓝牙的场景很多,如共享单车,智能手环,蓝牙打印机,蓝牙万用表,蓝牙门锁等
今天我们讨论在flutter中如何开发与蓝牙相关的app。
小伙伴们对蓝牙使用流程不是很了解的情况,建议去恶补一下。我这里也只是简单提到
0.打开蓝牙,蓝牙权限判断等
1.扫描设备,找到目标设备
2.连接设备
3.扫描已连接设备下的服务,可能有多个服务(fff0,fff1,fff2,fff3,fff4,fff5等)
4.针对某一个服务,扫描它的特征,可能有多个特征
5.有些特征是可读,可写,有的特征只能读操作,有的只能写操作,有的特征只通知
6.根据不同的特征,做相应的处理,可以对下位机发命令,也可以读取下位机的相关信息等
正题
下面将从零开始,在flutter里面写一个关于蓝牙万用表的app
一.创建工程
1.创建一个项目,如下图
2.然后就是下一步,下一步,直到最后一步,要勾选支持swift,kotlin的选项,因为现在很多第三方库都要支持swift,要不然在后面引入第三方库时,会有很多报错!
3.创建完工程后,点击到pubspec.yaml文件,点击右上角的Pub get,获取一下依赖,然后点击运行,看能不能正常跑起来
4.如果没有报错,跳过此步骤,如果报错了,去原生工程里面配置一下
4.1 点击工程文件,右键一下,如下图
4.2 配置一下iOS 开发者团队,如果没有话,就去申请开发都账号吧
5.再回到flutter工程,把工程跑起来
二.选择第三方库,封装一个蓝牙工具,方便使用及后期的维护工作
我这里选择了https://pub.dev/packages/flutter_blue,flutter_blue这个蓝牙库,他适配了iOS Android,也支持了空安全。
有了第三方库,我们需要对flutter_blue进行简单封装一下,ble_tool,具体代码如下:
import 'dart:async';
import 'package:flutter_blue/flutter_blue.dart';
import 'dart:developer';
import 'dart:core';
typedef ScanResultHandler = void Function(List<ScanResult>? datas);
typedef CharacteristicHandler = void Function(List<int>? datas);
class BleManager {
FlutterBlue? _flutterBlue;
factory BleManager() => _getInstance();
static BleManager get instance => _getInstance();
static BleManager? _instance;
BleManager._internal() {
_flutterBlue = FlutterBlue.instance;
}
static BleManager _getInstance() {
if (_instance == null) {
_instance = BleManager._internal();
}
return _instance!;
}
startScan(ScanResultHandler dataHandler, {int timeout = 60}) {
log("_scan");
// _flutterBlue?.startScan(timeout: Duration(seconds: timeout));
_flutterBlue?.startScan(timeout: Duration(seconds: timeout),withServices: [Guid("0000fff0-0000-1000-XXXX-XXXXXXXXXXX")]);
_flutterBlue?.scanResults.listen(dataHandler);
}
stopScan() {
log("_stopScan");
_flutterBlue?.stopScan();
}
Future<void> connectDevice(BluetoothDevice device) async {
log("_connect");
await device.connect(autoConnect: false);
}
Future<List<BluetoothService>> deviceToDiscoverServices(
BluetoothDevice device) async {
return await device.discoverServices();
}
Future<bool> characteristicToSetNotifyValue(
BluetoothCharacteristic characteristic) async {
return await characteristic.setNotifyValue(true);
}
listenCharacteristicValue(BluetoothCharacteristic characteristic,
CharacteristicHandler characteristicHandler) {
characteristic.value.listen(characteristicHandler);
}
Future<Null> characteristicToWriteValue(
BluetoothCharacteristic characteristic, List<int> list,{bool withoutResponse = false}) async {
log("_write withoutResponse = $withoutResponse",);
return await characteristic.write(list,withoutResponse: withoutResponse);
}
Future<List<int>> characteristicToReadValue(
BluetoothCharacteristic characteristic) async {
log("_read");
return await characteristic.read();
}
Future<List<BluetoothDevice>>? getConnectedDevices() {
return _flutterBlue?.connectedDevices;
}
Future<dynamic> disconnectDevice(BluetoothDevice device) async {
log("_disconnect");
return await device.disconnect();
}
}
三.使用封装好的蓝牙工具类ble_tool
使用之前需要对iOS工程,Android工程加一些权限
iOS 如下图
android如下图
开始扫描
BleManager.instance.startScan(scanResultHandler, timeout: 10);
扫描结果监听
void scanResultHandler(List<ScanResult>? results) {
print('results ====> $results');
for (ScanResult r in results!) {
print('${r.device.name} found! rssi: ${r.rssi}');
}
}
停止扫描
BleManager.instance.stopScan();
连接设备并且去扫描设备的服务services
BleManager.instance.connectDevice(widget.device).then((e) {
_discoverServices();
});
扫描设备服务,过滤服务0000fff0-0000-1000-XXXX-XXXXXXXXXXX,简称fff0, 并且扫描fff0服务下的所有特征
(_characteristicForFFF1,_characteristicForFFF2等)
_discoverServices() async {
List<BluetoothService> services =
await BleManager.instance.deviceToDiscoverServices(widget.device);
print("+++++++$services");
if (services == null) return;
services.forEach((service) {
// do something with service
print("uuid=${service.uuid} deviceId=${service.deviceId}");
if (service.uuid.toString() == "0000fff0-0000-1000-XXXX-XXXXXXXXXXX") {
print("---service is fff0---");
var characteristics = service.characteristics;
for (BluetoothCharacteristic c in characteristics) {
// log("----BluetoothCharacteristic-->$c");
print("----BluetoothCharacteristicUUID-->${c.uuid}");
if (c.uuid.toString().contains("fff1")) {
print("is fff1");
_characteristicForFFF1 = c;
} else if (c.uuid.toString().contains("fff2")) {
print("is fff2");
_characteristicForFFF2 = c;
_readDeviceBasicInfo();
} else if (c.uuid.toString().contains("fff3")) {
print("is fff3");
_characteristicForFFF3 = c;
} else if (c.uuid.toString().contains("fff4")) {
print("is fff4");
_characteristicForFFF4 = c;
_characteristicFFF4SetNotify();//fff4这个特征是只通知的,所以要设置通知setNotify,后面可以监听特征值上报
} else if (c.uuid.toString().contains("fff5")) {
print("is fff5");
}
}
}
});
}
断开蓝牙连接
BleManager.instance
.disconnectDevice(widget.device)
.then((value) => print("disconnected !!"));
监听特征值上报,主要的数据来自这里
_characteristicFFF4SetNotify() async {
await _characteristicForFFF4!.setNotifyValue(true);
// ignore: missing_return
BleManager.instance.listenCharacteristicValue(_characteristicForFFF4!,
(data) {
print("object=>>>>>>$data");
if (data == null) {
print("data=null>>>>>>");
return;
}
}
}
对设备设置命令,发送请求(写操作)
BleManager.instance
.characteristicToWriteValue(_characteristicForFFF3!, list)
.then((value) => print("write result:$value"));
读取设备的信息(读操作)
BleManager.instance
.characteristicToReadValue(_characteristicForFFF2!)
.then((value) {
print("fff2 value=$value");
});
这样蓝牙的相关操作,基本全部结束了,最后来看一下效果吧
结尾
蓝牙其他相关文章
flutter 实战App 之 提词器app
flutter 蓝牙ble(blue tooth),同时连接多台/多个设备
iOS 解决蓝牙配对弹框的问题,解决ANCS带来的问题,获取已配对(已绑定)设备列表
flutter的蓝牙还是挺方便的, 做一般的蓝牙应用还是可以的哦,小伴们,觉得有点用的话,或者已经看到这里面来的请点个赞吧~~ 后续分享更多有关flutter的文章。如果有疑问的话,请在下方留言~