Android|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|Android BLE蓝牙连接异常处理】Android-BLE-Issues

    推荐阅读