Flutter BLE应用的开发-flutter_blue

一、写在前面的话

本文主要介绍在Flutter环境下开发BLE应用。主要包含以下内容:判断蓝牙是否开启、判断是否有位置权限、扫描设备、

连接设备、监听设备上报的数据(Notify)、向设备发送数据、监听设备的断开等。内容虽然简单,但是很详细。

二、开始

1、使用到的库

flutter_blue: ^0.7.1+1
permission_handler: “^3.2.0” # 权限
众所周知,Flutter要使用原生的能力,就需要有原生库的支持,这里我们使用了flutter_blue来开发跟BLE相关的功能,permission_handler来开发权限检测以及申请权限的功能。在使用flutter_blue开启扫描的时候,插件会弹出系统的权限申请窗口,但是点击授权以后报了一个空指针,可能是插件存在的一个BUG,所以这里我们用permission_handler插件来处理权限相关的问题。(友情提示:在Android上扫描Ble需要位置权限)

2、flutter_blue的用法

import ‘package:flutter_blue/flutter_blue.dart’;
FlutterBlue flutterBlue = FlutterBlue.instance;
导包和初始化。

3、判断蓝牙是否开启

@override
void initState() {
super.initState();
flutterBlue.state.listen((state){
if(state == BluetoothState.on){
print(‘蓝牙状态为开启’);
isBleOn = true;
}else if(state == BluetoothState.off){
print(‘蓝牙状态为关闭’);
isBleOn = false;
}
});
}
在路由初始化的时候开启对蓝牙状态的监听。

if(!isBleOn){
ToastUtils.toast(context, “手机蓝牙未打开,请打开后再扫描设备”);
return;
}
在开始之前对蓝牙开启状态进行判断。

4、判断位置权限

PermissionUtils.checkPermissions(PermissionGroup.location).then((v) {
if (v) {
Navigator.pushNamed(context, “/device_page”);
} else {
PermissionUtils.showDialog(context, “提示”, “扫描蓝牙需要位置权限”, () async {
Navigator.pop(context);
await PermissionHandler()
.requestPermissions([PermissionGroup.location]);
PermissionStatus permission = await PermissionHandler()
.checkPermissionStatus(PermissionGroup.location);
if (permission == PermissionStatus.granted) {
Navigator.pushNamed(context, “/device_page”);
} else {
print(“no Permission to scan ble”);
ToastUtils.toast(context, “权限开启失败,请在系统设置中开启!”);
}
}, () {
Navigator.pop(context);
});
}
});
以上是对位置权限的处理,如果有,就进入扫描设备页面,没有的话申请权限,申请完之后在对其进行判断。因为本文的重点是ble,这里不对权限申请插件做过多的介绍。(PermissionUtils,dialog的源码会在文末附上)

5、扫描设备

flutterBlue.scan().listen((scanResult) {
// do something with scan result
var device = scanResult.device;
if (device.name.length > 10) {
if (deviceSet.indexOf(device) == -1) {
setState(() {
deviceSet.add(device);
});
}
print(
‘${device.name} found! rssi: s c a n R e s u l t . r s s i , a d d r e s s : {scanResult.rssi},address: scanResult.rssi,address:{device.id}’);
}
});
使用api进行ble扫描,我对蓝牙名进行了过滤,记得要存起来哦,连接的时候要用的。

6、连接设备

  await device.connect(autoConnect: false, timeout: Duration(seconds: 10));

这里的连接参数可以根据需要自己进行设置,我这里设置了10秒连接超时。这里我们一般还不能认为连接成功,还需要找到对应的读写服务和特征值。

BluetoothCharacteristic mCharacteristic;
List services = await device.discoverServices();
services.forEach((service) {
if (service.uuid.toString() == GattAttributes.BLE_SPP_SERVICE_READ) {
List characteristics =
service.characteristics;
characteristics.forEach((characteristic) {
if (characteristic.uuid.toString() ==
GattAttributes.BLE_SPP_NOTIFY_CHARACTERISTIC) {
mCharacteristic = characteristic;
}
});
}
// do something with service
});
以上便是根据uuid在对应的读写服务中找到对应Characteristic,至此,连接过程便已经完成了,可以进行页面跳转了。

7、读取设备的心跳

if (mNotifyCharacteristic != null) {
mNotifyCharacteristic.setNotifyValue(true);
mNotifyCharacteristic.value
.listen((value) => {print("device is online: " + value.toString())});
}
通过第6点的方法,找到可以notify的Characteristic,开启notify,然后监听其值。这里的setNotifyValue可能会有异常,具体请

参考我的前篇文章点我点我。下图是蓝牙设备传回的心跳。

8、向设备发送数据

Future write(List value, {bool withoutResponse = false})
我先查看源码可知write方法的参数是一个int型的list,那么我们只需把我们需要发送的数据放进这个list中就行了。

  mWriteCharacteristic.write([0x00,0x01]);

同样,获取mWriteCharacteristic的方法如上第6点所示。

9、监听设备的断开

device.state.listen((state){
if(state == BluetoothDeviceState.disconnected){
DialogUtils.showOneDialog(context, “提示”, “设备已断开连接”, (){
//do something
});
}
});
10、在不用页面获取device

await flutterBlue.connectedDevices.then((list) => {
if (list.length == 0) {Navigator.pop(context)} else {device = list[0]}
});
在不同的页面(路由)需要对设备进行读写操作,在设备的连接池中获取。

三、总结

本文归纳了flutter下使用ble对设备进行读写的详细步骤以及一些基本方法和注意事项,如果有问题的同学欢迎留言,博主会一一解答的。技术在于分享,开源的乐趣也在于此,如果本文有不够严谨的地方还望大佬支持。

附录

import ‘package:flutter/cupertino.dart’;

class DialogUtils{
static showDialog(BuildContext cxt, String title, String content,
ok(), cancel()) {
showCupertinoDialog(
context: cxt,
builder: (cxt) {
return CupertinoAlertDialog(
title: Text(title),
content: Text(content),
actions: [
CupertinoDialogAction(
child: Text(“确定”),
onPressed: () {
ok();
},
),
CupertinoDialogAction(
child: Text(“取消”),
onPressed: () {
cancel();
},
)
],
);
});
}
static showOneDialog(BuildContext cxt, String title, String content,
ok()) {
showCupertinoDialog(
context: cxt,
builder: (cxt) {
return CupertinoAlertDialog(
title: Text(title),
content: Text(content),
actions: [
CupertinoDialogAction(
child: Text(“确定”),
onPressed: () {
ok();
},
)
],
);
});
}
}
import ‘package:flutter/cupertino.dart’;
import ‘package:permission_handler/permission_handler.dart’;

/// 权限管理工具类
class PermissionUtils {
/// 检测相关权限是否已经打开(根据已有状态值)
static bool checkPermissionsByStatus(List lists) {
bool result = true;

for (PermissionStatus permissionStatus in lists) {
  if (permissionStatus != PermissionStatus.granted) {
    result = false;
    break;
  }
}

return result;

}

/// 检测相关权限是否已经打开(根据已有权限名称)
static Future checkPermissionsByGroup(
List lists) async {
bool result = true;

for (PermissionGroup permissionGroup in lists) {
  PermissionStatus checkPermissionStatus =
  await PermissionHandler().checkPermissionStatus(permissionGroup);

  if (checkPermissionStatus != PermissionStatus.granted) {
    result = false;
    break;
  }
}

return result;

}
static Future checkPermissions(PermissionGroup permissionGroup) async{
bool result = true;

PermissionStatus checkPermissionStatus =
await PermissionHandler().checkPermissionStatus(permissionGroup);

if (checkPermissionStatus != PermissionStatus.granted) {
  result = false;

}
return result;

}

/// 权限提示对话款
static showDialog(BuildContext cxt, String title, String content,
ok(), cancel()) {
showCupertinoDialog(
context: cxt,
builder: (cxt) {
return CupertinoAlertDialog(
title: Text(title),
content: Text(content),
actions: [
CupertinoDialogAction(
child: Text(“去开启”),
onPressed: () {
ok();
},
),
CupertinoDialogAction(
child: Text(“取消”),
onPressed: () {
cancel();
},
)
],
);
});
}
}
————————————————
版权声明:本文为CSDN博主「Andy__Wu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/WUWUWEIWEILONGLONG/article/details/119783439

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值