【IoT】产品设计之 Android BLE 蓝牙连接异常

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liwei16611/article/details/90437218

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

1、连接

连接失败可能是设备端原因,也可能是手机端原因。

不同的手机来自不同的厂家,用的不同的芯片和蓝牙协议栈都会导致蓝牙功能的表现不一致,这都会导致各式各样的兼容性问题,可能有的手机连接成功率高,有的成功率低。

设备端原因可能有些时候出现异常导致死机无响应,或某些参数设置得有问题。

但对于 Android 应用层开发来说,能做的很有限,蓝牙通信是在系统服务进程中处理的,我们无法跨进程改变系统的行为,如果是在一个进程我们还可能通过 Hook 等手段来调整其内在逻辑。

另外应用层的接口只是将请求封装传递给系统服务进程,并未做一些实质性的通信,所以应用层虽然是同一个进程的,但是 Hook 意义也不大。

所以我们能做的仅仅是看怎样调整接口的调用,使得整体稳定性更好一点而已。

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

1)关于超时

一般是设备不在周围,或设备断电未发广播,或设备当前被其他人连接。

系统默认超时为 30s,通常返回 133,我们也可以自己设置更短的超时时间,超时则 closeGatt,然后重新连接。

2)关于提前返回失败

一般是有明确的异常,可能是手机蓝牙的异常或者设备异常。

这两种情况建议 closeGatt,延时 500ms,然后重试。

如果重试三次仍然失败,则可以考虑提示用户重启手机蓝牙,或者检查设备是否正常工作。

还有一种情况,连接成功后没过多久连接又断开了,这有可能是设备主动断开,连接成功后有的设备会等待鉴权,如果一定时间内手机端还未发起鉴权则设备端主动断开。

也可能连接信道不够稳定导致断开的,此时 closeGatt 并重新连接即可。

当连接断开时,会收到 onConnectionStateChanged 回调,这个回调可能会有一定延时,甚至有 5s 以上。

解决的办法是轮询,如每隔 1s 发起一次读请求,如果连接断了会立即返回失败。

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

2、发现服务

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

当连接建立后,可以由设备端发起更改连接间隔,这样能加快后续发现服务以及数据读写的速度。

有的手机 discover service 很慢,原因是 connect interval 太大了,有的手机会主动向设备发起更改 connect interval,而有的手机却不会。

这样的话 connect interval 相差就会很大,实践中发现有的手机是 7ms,有的手机是默认的 50ms,所以发现 service 都要 8s,甚至 20s 的都很寻常,这对用户来说是无法忍受的。

所以比较好的办法是设备主动发起更改 connect interval,而 Android 系统是没有提供对应 API 的。

如果发现服务失败,通常来说不用 closeGatt,重试一下就好了。

如果重试三次还失败,建议清一下缓存,再 closeGatt,重新连接。

3、读写

读写读写失败要看失败的原因是什么,如果是权限问题,则需要和设备端确认是否开放了相应的读写权限。

也可能是要读写的 character 不存在,可能是设备端修改了固件,手机端需要刷新一下蓝牙缓存,closeGatt 再重新连接。

如果是其它未知错误,则重试三次,仍然失败则 closeGatt。不过通常来说如果是因为连接出了问题导致读写失败的,会收到 onConnectionStateChanged 回调,此时就不用再无谓的重试了,直接 closeGatt,重新连接。

4、通知

通知打开/关闭 character 的 notify,必须等收到 onDescriptorWrite 回调之后才算结束,才能开始下一个任务。如果打开 notify 失败,则可以改成周期性轮询的方式去查询 character 的值。


refer:

https://www.jianshu.com/p/a581dfe315b9
https://github.com/iDevicesInc/SweetBlue/wiki/Android-BLE-Issues


 

猜你喜欢

转载自blog.csdn.net/liwei16611/article/details/90437218