当前位置:首页 » 安卓系统 » androidble断开

androidble断开

发布时间: 2022-12-25 02:37:26

A. 安卓BLE知识及EasyBle的使用

BLE(Bluetooth low energy)蓝牙低功耗是蓝牙4.0新增的子规范,其具有低能耗、低成本、低延迟、传输距离长等特点,自安卓4.3(api level 18)起,安卓开始支持BLE。BLE与经典蓝牙对比如下图():

在讲链接参数之前,需要先了解连接事件Connection Events
1)Conection Events(连接事件)
蓝牙设备建立连接后,所有信息的交换都是通过Connetion Events进行的,主设备在Connection Events开始起发送数据包,从属设备在Connection Events期间回复。Connection Events是周期性出现的且时间间隔很短,在一个Connection Events中,器件最大电流为十几mA,平均电流1uA,这便是BLE功耗较低的原因。Connection Events如下图()

2)链接参数
在两个蓝牙设备建立连接进入连接状态前,蓝牙设备需要设置一系列的链接参数,链接参数是在中心设备向外围设备发起连接请求时传递的:

当外围设备认为中心设备请求的链接参数不合适时,外围设备可在连接期间发送一个 Connetion Parameter UpdateRequest 请求中心设备更改链接参数。当中心设备收到请求时可接受或拒绝外围设备的链接参数更新请求

GATT层级图如下(图片来自 蓝牙官网 )

MTU(Maximum Transmission Unit): 即数据的最大传输单元。具体是指一个Chracteristic一次性可传输的数据大小。
蓝牙核心规范(core spec)中定义了ATT的默认MTU为23byte,除去ATT的opcode一个字节以及ATT的handle2个字节之后,剩下的20个字节便是留给GATT的了。由于ATT的最大长度为512byte,故一般认为MTU的最大长度为512个byte。
注:core spec规定每一个设备都必须支持MTU为23。

用系统api开发参见 安卓BLE开发官方文档
这里介绍使用第三方库 EasyBle 快速开发BLE

在项目根gradle中添加

在具体mole的gradle中添加

1)判断设备是否支持BLE并打开蓝牙

安卓版本不小于6.0的,扫描必须要有定位权限,若版本为Android10及以上,则需精确定位权限(即 Manifest.permission.ACCESS_FINE_LOCATION )

当需要结束扫描时用以下方法结束扫描,建议在扫描到目标设备后停止扫描

当需要断开与设备的连接时可使用以下任一方法断开设备连接

notify和indicate都使用以下方法

当需要取消notify或indicate时调用以下方法

如果一次性写入的数据长度大于MTU即最大传输单元(默认是20字节),则可以使用下列方法进行分批写入

当结束BLE通信时不要忘了调用destroy


B. 如何使用android原生BLE蓝牙进行操作

之前的涉及的物联网项目中使用的: BLE 低功耗蓝牙(蓝牙4.0), 支持android 4.3以上的手机
主从关系: BLE低功耗蓝牙只能做从端设备 ,一个蓝牙主端设备,可同时与7个蓝牙从端设备进行通讯

1)低功耗
低功耗的原理:
1低功耗蓝牙仅使用了3个广播通道,传统蓝牙技术采用 16~32 个频道
2每次广播开启时间也由传统的 22.5ms 减少到 0.6~1.2ms(毫秒)

2)传输距离极大提高
传统蓝牙传输距离为 2~10m,而蓝牙4.0的有效传输距离可达到 60~100m

3)安全性
使用AES-128 CCM加密算法进行数据包加密和认证。
更多BLE蓝牙的解析参考博客 : BLE4.0教程一 蓝牙协议连接过程与广播分析

添加权限
打开蓝牙
1.先拿到BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
2.再拿到BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
判断是否打开蓝牙
未打开弹出 系统弹框 ,除了 魅族手机 是打开系统设置

设备/手机都是蓝牙信号

在回调方法中:

一般在扫描的过程中,我们还会设置 设备过滤原则 (因为我只想要搜索到我们想要的设备,忽略无关设备)
如:从 scanRecord -- beacon -- beacon.type == 0xFF代表Manufacture,通过与嵌入式软件定义 自己的 Manufacture值即可

用BluetoothDevice得到BluetoothGatt:

断连:

关键问题:连接后一般要做什么事?

( 必须在刚连接成功后2秒内app写一个值给设备,否则会被设备断开连接)

主要是读写 characteristic
gatt.wirteCharacteristic(mCurrentcharacteristic);

gatt.readCharacteristic(characteristic);

bluetoothGatt.setCharacteristicNotification(data, true);

真实工作中使用的蓝牙库BlueToothKit请参考我的另一篇博客:
android蓝牙入门知识和优秀蓝牙第三方库BluetoothKit的使用

C. Android BLE蓝牙踩坑总结

自从 Android-BLE 库开源了一段时间以来,越来越多的小伙伴问到了各种各样的关于BLE的奇怪问题,在这里我想跟大家分享一下本人对于Android BLE蓝牙的一些看法和解决方式,避免刚接触的小伙伴再次踩坑。

很多人曾问过我这个问题,为什么其他手机都没什么问题,就华为的一些手机老是连接不稳定,经常连接的很慢,而且连接上还经常断开。的确,在这里强调一下华为的一部分手机确实很容易出现这种问题,有时候软件、硬件都搞不定,而且经常性收到客户投诉关于华为手机连接稳定性问题,这个的确没有完全解决的办法,只能靠App和硬件的优化,并不是想甩锅给华为,咱也不敢问到底是什么原因,而且我们公司专门针对各个Android版本的手机做过测试,包括蓝牙传输速率的测试,最后发现华为P20的速度竟然跟小米8的速度差了好几倍,按理说P20手机也不便宜啊,为什么手机蓝牙芯片不能做的再好一点呢?

BLE扫描滥用预防

AOSP-BLE扫描滥用说明

息屏状态下,蓝牙扫描日志,因为扫描周期是12s,所以打印的时间戳间隔是12s,这里的日志为系统日志。

https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/include/bt_target.h#1428

stackoverflow问答社区

D. Android BLE蓝牙连接异常处理

蓝牙通信过程中异常很常见,大致有以下几种:

1,连接

2,发现服务

3,读写

4,通知

连接失败可能是设备端原因,也可能是手机端原因。不同的手机来自不同的厂家,用的不同的芯片和蓝牙协议栈都会导致蓝牙功能的表现不一致,这都会导致各式各样的兼容性问题,可能有的手机连接成功率高,有的成功率低。设备端原因可能有些时候出现异常导致死机无响应,或某些参数设置得有问题。但对于Android应用层开发来说,能做的很有限,蓝牙通信是在系统服务进程中处理的,我们无法跨进程改变系统的行为,如果是在一个进程我们还可能通过Hook等手段来调整其内在逻辑。另外应用层的接口只是将请求封装传递给系统服务进程,并未做一些实质性的通信,所以应用层虽然是同一个进程的,但是Hook意义也不大。所以我们能做的仅仅是看怎样调整接口的调用,使得整体稳定性更好一点而已。

连接失败分两种,一种是超时,一种是提前返回失败。

关于超时,一般是设备不在周围,或设备断电未发广播,或设备当前被其他人连接。系统默认超时为30s,通常返回133,我们也可以自己设置更短的超时时间,超时则closeGatt,然后重新连接。

关于提前返回失败,一般是有明确的异常,可能是手机蓝牙的异常或者设备异常。

这两种情况建议closeGatt,延时500ms,然后重试。如果重试三次仍然失败,则可以考虑提示用户重启手机蓝牙,或者检查设备是否正常工作。

还有一种情况,连接成功后没过多久连接又断开了,这有可能是设备主动断开,连接成功后有的设备会等待鉴权,如果一定时间内手机端还未发起鉴权则设备端主动断开。也可能连接信道不够稳定导致断开的,此时closeGatt并重新连接即可。

当连接断开时,会收到onConnectionStateChanged回调,这个回调可能会有一定延时,甚至有5s以上。解决的办法是轮询,如每隔1s发起一次读请求,如果连接断了会立即返回失败。

如果蓝牙连接不稳定,可以考虑关掉WIFI,因为WIFI通常和蓝牙共用一个天线。

有的手机上discoverService可能会回调不止一次onServiceDiscover,这个要注意防御。

当连接建立后,可以由设备端发起更改连接间隔,这样能加快后续发现服务以及数据读写的速度。有的手机discover service很慢,原因是connect interval太大了,有的手机会主动向设备发起更改connect interval,而有的手机却不会。这样的话connect interval相差就会很大,实践中发现有的手机是7ms,有的手机是默认的50ms,所以发现service都要8s,甚至20s的都很寻常,这对用户来说是无法忍受的。所以比较好的办法是设备主动发起更改connect interval,而Android系统是没有提供对应API的。

如果发现服务失败,通常来说不用closeGatt,重试一下就好了。如果重试三次还失败,建议清一下缓存,再closeGatt,重新连接。

读写失败要看失败的原因是什么,如果是权限问题,则需要和设备端确认是否开放了相应的读写权限。也可能是要读写的character不存在,可能是设备端修改了固件,手机端需要刷新一下蓝牙缓存,closeGatt再重新连接。如果是其它未知错误,则重试三次,仍然失败则closeGatt。不过通常来说如果是因为连接出了问题导致读写失败的,会收到onConnectionStateChanged回调,此时就不用再无谓的重试了,直接closeGatt,重新连接。

打开/关闭character的notify,必须等收到onDescriptorWrite回调之后才算结束,才能开始下一个任务。

如果打开notify失败,则可以改成周期性轮询的方式去查询character的值。

可参考该文章

Android-BLE-Issues

E. flutter_ble Android 设备蓝牙BLE 无法断开重新问题

https://github.com/pauldemarco/flutter_blue/issues/525
connect() method:

disconnect() method

F. android ble为什么自动断开连接

可以直接把ble的电源关闭。也可以在手机设置中,打开蓝牙,会看到已连接设备,点来,取消连接就可以了。

热点内容
安卓手机投屏到电视上怎么切换 发布:2025-04-07 06:22:02 浏览:375
支票密码多少位 发布:2025-04-07 06:16:09 浏览:279
php观察 发布:2025-04-07 06:16:06 浏览:865
累不存储 发布:2025-04-07 06:09:42 浏览:362
pythonos删除文件 发布:2025-04-07 05:59:02 浏览:366
少儿编程哪家最好 发布:2025-04-07 05:52:01 浏览:304
asp文件上传代码 发布:2025-04-07 05:52:00 浏览:996
泰坦之旅安卓版如何注册 发布:2025-04-07 05:50:43 浏览:892
服务器除了云锁还有什么软件 发布:2025-04-07 05:46:32 浏览:424
温泉服务器地址 发布:2025-04-07 05:46:26 浏览:521