一、写在前面的话

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

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

二、开始

1、使用到的库

  flutter_blue: ^0.7.1+1permission_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、判断蓝牙是否开启

@overridevoid 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 resultvar device = scanResult.device;if (device.name.length > 10) {if (deviceSet.indexOf(device) == -1) {setState(() {deviceSet.add(device);});}print('${device.name} found! rssi: ${scanResult.rssi},address:${device.id}');}});

使用api进行ble扫描,我对蓝牙名进行了过滤,记得要存起来哦,连接的时候要用的。

6、连接设备

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

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

BluetoothCharacteristic mCharacteristic;
List<BluetoothService> services = await device.discoverServices();services.forEach((service) {if (service.uuid.toString() == GattAttributes.BLE_SPP_SERVICE_READ) {List<BluetoothCharacteristic> 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<Null> write(List<int> 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<int>(context: cxt,builder: (cxt) {return CupertinoAlertDialog(title: Text(title),content: Text(content),actions: <Widget>[CupertinoDialogAction(child: Text("确定"),onPressed: () {ok();},),CupertinoDialogAction(child: Text("取消"),onPressed: () {cancel();},)],);});}static showOneDialog(BuildContext cxt, String title, String content,ok()) {showCupertinoDialog<int>(context: cxt,builder: (cxt) {return CupertinoAlertDialog(title: Text(title),content: Text(content),actions: <Widget>[CupertinoDialogAction(child: Text("确定"),onPressed: () {ok();},)],);});}
}
import 'package:flutter/cupertino.dart';
import 'package:permission_handler/permission_handler.dart';/// 权限管理工具类
class PermissionUtils {/// 检测相关权限是否已经打开(根据已有状态值)static bool checkPermissionsByStatus(List<PermissionStatus> lists) {bool result = true;for (PermissionStatus permissionStatus in lists) {if (permissionStatus != PermissionStatus.granted) {result = false;break;}}return result;}/// 检测相关权限是否已经打开(根据已有权限名称)static Future<bool> checkPermissionsByGroup(List<PermissionGroup> 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<bool> 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<int>(context: cxt,builder: (cxt) {return CupertinoAlertDialog(title: Text(title),content: Text(content),actions: <Widget>[CupertinoDialogAction(child: Text("去开启"),onPressed: () {ok();},),CupertinoDialogAction(child: Text("取消"),onPressed: () {cancel();},)],);});}
}

Flutter:手把手教你进行BLE应用的开发-flutter_blue相关推荐

  1. 手把手教你iPhone 3G手机软件开发

    手把手教你iPhone 3G手机软件开发 "iPhone 是一款革命性的.不可思议的产品,比市场上其它任何移动电话整整领先了五年,"苹果公司首席执行官史蒂夫·乔布斯如是说,&quo ...

  2. 实例:用C#.NET手把手教你做微信公众号开发(20)--使用微信支付线上收款:jsapi方式

    在做线上.线下销售时,可以使用微信便捷支付,通过微信公众号收款有很多种收款方式,如下图: 今天我们来讲一下jsapi支付,场景就是在微信内打开某个页面,完成在线支付,同样一个网页,使用微信打开就是js ...

  3. 小白都能看懂的实战教程 手把手教你Python Web全栈开发(DAY 3)

    小白都能看懂的实战教程 手把手教你Python Web全栈开发 Flask(Python Web)实战系列之在线论坛系统 第三讲 这是小白都能看懂的实战教程 手把手教你Python Web全栈开发 的 ...

  4. 正点原子linux驱动教程,正点原子 手把手教你学Linux之驱动开发篇

    简 介 该课程是正点原子手把手教你学Linux系列课程,该课程配套开发板为正点原子alpha/mini Linux开发板. 手把手教你学Linux之驱动开发篇: 第1讲 Linux驱动开发与裸机开发区 ...

  5. 实例:用C#.NET手把手教你做微信公众号开发(21)--使用微信支付线上收款:H5方式

    在做线上.线下销售时,可以使用微信便捷支付,通过微信公众号收款有很多种收款方式,如下图: 今天我们来讲一下H5场景支付,使用手机浏览器打开就是H5方式,最常见的推广是短信内置链接,这种场景需要调用微信 ...

  6. 小白都能看懂的实战教程 手把手教你Python Web全栈开发(DAY 1)

    小白都能看懂的实战教程 手把手教你Python Web全栈开发 Flask(Python Web)实战系列之在线论坛系统 第一讲 博主博客文章内容导航(实时更新) 更多优质文章推荐: 收藏!最详细的P ...

  7. 16w行的nginx源码,如何分拆模块阅读,手把手教你造轮子丨Nginx模块开发丨C/C++丨Linux服务器开发丨后端开发

    16w行的nginx源码,如何分拆模块阅读,让你明白轮子如何造  1. 多进程模型下的惊群处理 2. 内存池的代码封装 3. slab共享内存分配 视频讲解如下,点击观看: 16w行的nginx源码, ...

  8. 手把手教你Linux下基于ITK开发基础(1)

    手把手教你Linux下基于ITK开发基础(1) *requirement: requirement version git 2.17.1 g++ Ubuntu 7.5.0-3 ubuntu1~18.0 ...

  9. 手把手教你进行微信小程序开发案例1---计算器

    由于之前的文章中已经教会了大家如何注册自己的一个微信小程序,并且利用微信开发工具进行小程序的开发,所以这里不再介绍如何下载工具和注册账号,不懂的小伙伴们可以观看我之前发过的教程哦. #####下面我将 ...

最新文章

  1. python pycharm 包 安装问题
  2. HDU4587(割点+最大连通分量)
  3. 关于使用JAVA中JDK安装和在命令行中编译和运行程序的一些总结
  4. MyBatis 插入数据库返回主键
  5. openstack-Mitaka Glance上传镜像报错
  6. Java之【线程通信】--标志位练习
  7. 数据分析:度量数据散布的四分位数
  8. WebBrowser设置打印页眉页眉和页边距
  9. AngularJs 实战 -慕课网
  10. 小红的记谱法(模拟+前缀和)
  11. 51Nod 1182
  12. 联想笔记本linux无线网卡驱动下载,联想无线网卡驱动下载-联想 X1 Carbon网卡驱动下载v18.40.0 官方最新版-西西软件下载...
  13. 单摄像机对于二维平面的测量
  14. java解二元一次方程组_如何用C语言解二元一次方程组
  15. 计算机第四轮学科评估排名,最权威中国高校学科排名,全国第四轮学科评估结果出炉!...
  16. 什么是项目管理,如何做好项目管理?
  17. flex 解析 html5,Flex布局详解
  18. Mac本,pip命令下载速度慢怎么办,这里有方案
  19. 不同应用选择荧光染料 -CY7 ALK脂溶性Sulfo-Cyanine7 alkyne 结构式应用
  20. html控制复选框选中,选中HTML复选框

热门文章

  1. 【异界双子-twin souls-】Tech Support
  2. 罗马音平假名中文可复制_如何快速有效地学习日语五十音?
  3. odoo15 csv 格式文件加载 中华民簇表
  4. Hilary Stagg 不死传说
  5. mysql存储过程select into_mysql存储过程select into
  6. ESP8266 网络服务器仪表显示传感器读数
  7. bug的生命周期你知道吗?一张图带你看懂它!
  8. Python OJ输入输出
  9. route和bridge是什么意思_请问ROUTE 和 BRIDGE 是怎么分别的!
  10. 堆、栈的概念及使用特性