首先,android设备与蓝牙连接有两种方式。不同的连接,代码是不一样的,应该是uuid不一样。
1. android设备 与android设备连接。
2. android设备 与非android设备连接。
如下图
我做的是与非android蓝牙设备相关的通讯,以下全为非android蓝牙设备的相关内容。
蓝牙目前可以分为2种。
经典蓝牙(Classic)
低功耗蓝牙(BLE android4.3以上支持ble)
这两种蓝牙从扫描到连接到数据的传输api完全不一样,因此拿到蓝牙设备之后,要确认好蓝牙种类。
关于BLE蓝牙,可参考谷歌官方demo
https://github.com/googlesamples/android-BluetoothLeGatt
由于这个官方代码是很久之前的,因此,在android6.0以及以上的系统需要加上权限的相关设置。
并且这里只有读,没有写入数据的操作。
写入的操作,我是参考的这个。
https://github.com/Jasonchenlijian/FastBle
经典蓝牙,参考了这个demo,连接的时候有一个选项,不要选与android设备相连,选另一个。
https://github.com/akexorcist/Android-BluetoothSPPLibrary
我是在这个demo的基础上进行修改。
Android-BluetoothSPPLibrary应该是在官方demo的基础上修改的。
https://github.com/googlesamples/android-BluetoothChat
目前是使用经典蓝牙串口调试通讯(ble蓝牙只做了扫描、连接到读写数据等)。
使用SSCOM5.12(pc端软件)这个串口调试工具。当android设备与蓝牙连接之后,通过app发送命令,电脑上就可以收到数据(蓝牙要通过线连接到电脑)。
期间遇到的问题:
未断开的情况下重连,要先做断开操作,然后在断开后要加一定的延时再进行重新连接,否则容易报错。
Android-BluetoothSPPLibrary 的代码中数据的发送与接收那里在断开与重连的过程中容易报错,改成跟 android-BluetoothChat一样就不会报错了。
根据Android-BluetoothSPPLibrary 修改的代码,蓝牙断开后4.4直接崩溃。未断开的情况下重连 7.0不会报错,5.0以及6.0会无法连接,要断开后再连接才可以连接上。
解决完蓝牙的连接问题之后,下面来看看通讯问题。
蓝牙串口是什么。
首先看串口的解释:
https://zh.wikipedia.org/wiki/%E4%B8%B2%E8%A1%8C%E7%AB%AF%E5%8F%A3
串口包括RS-232-C、RS-422、RS485、USB等。
这里串口指的是usb接口。
蓝牙开发板上的usb接口通过线接到pc的usb接口。
串口是指利用串行方式传输数据的接口,它是一大类接口,USB接口、RS232接口、网线RJ45接口、RS485接口、SATA接口等等都属于串口。各种串口之间的通讯协议、接口电平等并不完全相同,因此有一种串口得到另一种串口时需要转换。
一般来说,串口默认是指RS232接口,所谓的USB转串口实际上就是USB转RS232装置。
https://zhidao.baidu.com/question/340354937.html
蓝牙模块也称蓝牙串口通讯模块
http://www.shaoguoji.cn/2016/04/16/usage-of-bluetooth-model/
蓝牙的真正作用就是代替了那根tx ,rx的数据线。
蓝牙通讯也有相关协议。
蓝牙协议相关:
https://langw.gitbooks.io/blesummary-/content/lan_ya_xie_yi_zhan_fen_xi.html
http://www.cnblogs.com/zjutlitao/p/4742428.html
可以粗略的看下,不必深入。
因此,蓝牙串口就是蓝牙开发板通过串口连接(这里是usb接口连接,实际应用中是可以自行封装串口通讯协议?通讯的本质是?协议?),进行通讯。
那么这里是怎么进行通讯的?
1.当android设备与蓝牙连接之后,app就可以发生数据到蓝牙模块。
2.蓝牙模块接收到命令之后,通过串口(这里是usb接口)传输给电脑,使用 SSCOM5.12软件读出数据。这里主要就是 SSCOM5.12这个软件的作用了。 使用SSCOM5.12串口调试助手的时候,注意设置波特率。
使用SSCOM5.12注意以下几处。
整个发送数据的流向是:
app--->android 设备蓝牙 -->非android设备蓝牙模块-->pc端--> 使用SSCOM5.12解析数据。
实际使用中非android设备蓝牙模块后面不会接到pc端,而是别的串口,这里只是前期调试。
实际使用如下
当app的蓝牙连接到非android设备的蓝牙模块时,会收到一条指令。
IM_CONN:0,683E344FA855,0100,0,490
01 00这个数据是发送数据时需要用到的。0100要反过来。00 01 。注意句柄(handle
https://www.zhihu.com/question/22950899)。
发送数据:
41 54 3E 01 01 08 00 00 01 31 32 33 34 35 36 0d
成功发送数据会返回ok,否则是error。
[15:24:22.762]发→◇AT>���\0\0�123456□
[15:24:22.767]收←◆
OK
蓝牙断开显示
[15:24:50.336]收←◆
IM_DISC:0100,0
以上就是经典蓝牙相关的。
------------------------------BLE----------------
下面来看看ble的。
ble相关概念看这篇,很详细。
Android 上的低功耗蓝牙实践
https://www.race604.com/android-ble-in-action/
BLE 的协议栈
作为 Android 开发者,我们不必理解 BLE 的协议栈每个细节,这里大概介绍一下协议架构。我们都知道,协议一般都是分层设计的。BLE 协议栈也不例外。我们来看一下这个图。整个协议栈大致分为三部分,从下到上分别为,控制器(Controller)→主机(Host)→应用(Applications)。
控制器:它是协议栈的底层的实现,直接与硬件相关,一般直接集成在 SoC 中,由芯片厂商实现,包括物理层和链路层。 主机:这是协议栈的上层实现,是硬件的抽象,与具体的硬件和厂家无关。 应用层:就是使用 Host 层提供的 API,开发的应用。
下面具体围绕这张图进行分析。
ATT与GATT
[翻译]ATT和GATT概述
http://legendmohe.net/2015/01/16/%E7%BF%BB%E8%AF%91att%E5%92%8Cgatt%E6%A6%82%E8%BF%B0/
ATT,即属性协议
GATT,全称叫做通用属性配置文件
上图 中的Host 部分,属性协议,即 ATT,它是 BLE 通信的基础。ATT 把数据封装,向外暴露为“属性”,提供“属性”的为服务端,获取“属性”的为客户端。ATT 是专门为低功耗蓝牙设计的,结构非常简单,数据长度很短。
接下来我们看一下 GATT,全称叫做通用属性配置文件,它是建立在前面说的 ATT 的基础上,对 ATT 进行进一步的逻辑封装,定义数据的交互方式和含义。
这是我们做 BLE 开发的时候直接接触的概念。
GATT 按照层级定义了三个概念:服务(Service)、特征(Characteristic)和描述(Descriptor)。他们的包含关系如右边这个图所表示的:一个 Service 包含若干个 Characteristic,一个 Characteristic 可以包含若干 Descriptor。而 Characteristic 定义了数值和操作。
Characteristic 的操作这几种权限:读、写、通知等权限。我们说的 BLE 通信,其实就是对 Characteristic 的读写或者订阅通知。
还有最外面一层,Profile配置文件,把若干个相关的 Service 组合在一起,就成为了一个 Profile,Profile 就是定义了一个实际的应用场景。
详细的图:
那么如何操作Characteristic ,关键在于UUID。
Service、Characteristic 还有 Descriptor 都是使用 UUID 唯一标示的。
下面来看看什么是uuid。
关于 UUID 有一些规范,为了避免冲突,一般都不会自己手动去定义。例如 Android 中提供了 UUID.randomUUID() 来生成一个随机的 UUID。我们也看到,UUID 有点太长了,在低功耗蓝牙中这种数据长度非常受限的情况下,使用起来肯定不方便,所以蓝牙又使用了所谓的 16 bit 或者 32 bit 的 UUID。其实本质上并没有什么 16bit 或者 32 bit UUID,蓝牙 SIG 定义了一个基础的UUID(Bluetooth Base UUID),形式如下。除了 XXXX 那几位意外,其他都是固定,所以说,其实 16 bit UUID 是对应了一个 128 bit 的 UUID。这样一来,UUID 就大幅减少了,例如 16 bit uuid 只有有限的 65536 个,所以 16 bit UUID 并不能随便使用。SIG 已经预先定义了一些 UUID,如果你想添加一些自己的 16 bit 的 UUID,可以花钱买。
16*16*16*16 = 65536
BLE 应用可以分为两大类:基于非连接的和连接的。
基于非连接的,这种应用就是依赖 BLE 的广播,也叫作 Beacon。这里有两个角色,发送广播的一方叫做 Broadcaster,监听广播的一方叫 Observer。
基于连接的,就是通过建立 GATT 连接,收发数据。这里也有两个角色,发起连接的一方,叫做中心设备—Central,被连接的设备,叫做外设—Peripheral。
我这里做的是连接式的应用。
这里总结一下扫描中一些建议。
1、首先,尽可能使用新的 API,功能更强大;
2、尽可能少地扫描,因为毕竟扫描是一个比较重的操作,耗电,也会减慢 BLE 连接速度;
3、扫描的时候,尽量设置 ScanFilter,只扫描那些你感兴趣的设备,而不是全盘扫描;
4、正确使用 API,特别是合理停止扫描,防止资源泄漏。
这里有一个中心设备和外设的概念。
可以尽量遵循如下一些原则:尽量少的连接数量,尽量短的连接时间,尽量少的扫描,至于尽量少的 ClientIf,如果在 APP 中多个模块中都要扫描或者连接,应该做尽可能的合并。尽量少的广播数据,尽量少的并行请求,在回调中要做尽量少的工作。
以上大部分文字都是抄的,这里只是做个记录。
具体代码分析可以看这里,可对照谷歌官方源码去参照。
Android BLE 蓝牙开发入门
https://www.jianshu.com/p/3a372af38103
BLE的坑:Android蓝牙4.0 BLE开发坑总结
参考连接:
https://www.mianbaoban.cn/blog/post/133095