Android蓝牙问题

Android BLE蓝牙易出现问题

有问题可以加QQ讨论:1070800492
蓝牙回调
Android 4.4的蓝牙回调是在异步线程(不在主线程),如要蓝牙回调在主线程执行更新界面操作,记得切换到主线程操作

三星手机兼容性问题
connectGatt()方法是在某些三星手机上只能在UI线程调用
备注:三星的手机connet和disconnet还有connectGatt都要在UI线程中操作

Android 新APL
Android换了一套扫描设备的API:BluetoothLeScaner.startScan(List,ScanSetings,ScanCallback)

Android 新的权限
Android 6.0动态权限,Android必须拥有定位权限才能扫描到BLE设备

连接不断开的问题
别的BLE程序非法保留连接的设备可能会导致连接不能断开

异步问题
读写Characteristic,Descriptor等几乎所有BLE操作结果都为异步返回,若不等待上一次操作结果返回就执行下一次操作,很可能导致操作失败或者操作无效,onDescriptorWrite()返回的线程写入的线程为同一个线程,别的操作一般在不同的线程回调

设备缓存
Android会对连接过的BLE设备进行Server进行缓存,如设备升级后Services等有改动,则程序会出现通信失败,此时就得刷新缓存,但是刷新缓存的方法没有对外开放,只能使用反射来调用BluetoothGatt类中的refresh()方法:

   try {
    Method localMethod = mBluetoothGatt.getClass().getMethod("refresh");
    if (localMethod != null) {
      return (Boolean) localMethod.invoke(mBluetoothGatt);
     }
    } catch (Exception localException) {
     Log.e("refreshServices()", "An exception occured while  refreshing device");
   }

扫描设备
startScan(UUID[],BluetoothAdapter.LeScanCallback)
在Android4.4及以下手机似乎只支持16位短的UUID,不支持128位完整的UUUID。

任何出错,超时,用完马上调用Gatt.disconnect(),Gatt.close()。

getBtAdapter().enable()是异步,立即返回,但从off到on的过程需要一个时间所以只能监听系统broadcast发出的intent里的state

多次扫描蓝牙,在华为荣耀,魅族M3 NOTE中有的机型会发生多次断开——扫描——断开——扫描…会扫描不到设备,此时需要在断开连接后,不能立即扫描,而是先停止扫描后,过2秒再扫描才能扫描到设备

扫描尽量不要放在主线程进行,可以放在子线程里,不然有些机型会出现do too many work in main thread.

设备的gatt在不用时要及时关闭,系统支持的连接的个数是有限的,当达到上限后无法再建立新的连接了。

当连接断开后要调closeGatt释放资源,不用调disconnect,也不要下次复用之前的gatt来reconnect,因为有的手机上重连可能会存在问题,比如重连后死活发现不了service。这种情况下,最好只要断开连接就close gatt,下次连接时打开全新的gatt,这样就可以发现service了。

BLE的特征一次读写最大长度20字节。

一个主设备(例如Android手机)可以同时连接多个从设备(一般为6个,例如智能硬件。超过就连接不上了),一个从设备只能被一个主设备连接,一旦从设备连接上主设备,就停止广播,断开连接则继续广播。在任何时刻都只能最多一个设备在尝试建立连接。如果同时对多个蓝牙设备发起建立Gatt连接请求。如果前面的设备连接失败了,则后面的设备请求会被永远阻塞住,不会有任何连接回调。所以建议:如果要对多个设备发起连接请求,最好是一个接一个的顺序同步请求管理。

对蓝牙设备的操作不能并行,只能串行,即每次都要在收到上一个操作的回调后才能继续下一个操作。但是断开连接例外,断开连接要马上closeGatt,不用等任务队列中的其他操作了。而且要给所有正在执行或者准备执行的任务都cancel。

有时候蓝牙协议栈出现异常可能收不到回调,所以我们要对每个操作做超时检查,否则后面的所有操作都被阻塞了。

对于超时的任务,最好closeGatt,下次重新连接的时候重开一个gatt。

蓝牙连接可能不稳定,最好支持失败自动重试机制,尤其是连接和发现服务,因为80%的问题都发生在建立连接和发现服务的时候,而且这一块也是最耗时的。

Android 从 4.3(API Level 18) 开始支持低功耗蓝牙,但是只支持作为中心设备 (Central) 模式,这就意味着 Android 设备只能主动扫描和链接其他外围设备 (Peripheral)。从Android 5.0(API Level 21)开始两种模式都支持。
BLE 官方文档在这里

在BluetoothAdapter.startLeScan()时候、
在BluetoothAdapter.LeScanCallback.onLeScan()中不能做太多事情,特别是周围的BLE设备多的时候,非常容易出现一下错误:

E/GKI  LINUX(17741): ##### ERROR : GKI exception: GKI  exception(): Task State Table E/GKI LINUX(17741): ##### 

E/GKI  LINUX(17741): ##### ERROR : GKI exception: TASK ID [0] task name [BTU] state [1] 

E/GKI 

LINUX(17741): #####

LINUX(17741): ##### ERROR : GKI 
exception: TASK ID [1] task name [BTIF] state [1]

LINUX(17741): ##### 


E/GKI  LINUX(17741): ##### ERROR : GKI exception: TASK ID [2] task name [A2DP-MEDIA] state [1] 

E/GKI 

LINUX(17741): #####

LINUX(17741): ##### ERROR : GKI  exception: GKI exception 65524 getbuf: out of buffers##### 


E/GKI  LINUX(17741): ##### ERROR : GKI exception: 

E/GKI_LINUX(17741):  * * * * * * * * * * * * * * * * * * * * * * 
  • 开发建议:在 onLeScan() 回调中只做尽量少的工作,可以把扫描到的设备,扔到另外一个线程中去处理,让 onLeScan() 尽快返回.

BLE设备的建立和断开连接的操作

  • 例如:BluetoothDevice.connectGatt(),BluetoothGatt.connect(),BluetoothGatt.disconnect()等操作最好都放在主线程中,否则你会遇到意想不到的麻烦**
  • 开发建议:对BluetoothGatt的连接和断开请求,都通过发送消息到Android的主线程中,让主线程来执行具体的操作,例如创建一个handler把消息发到主线程。

**如果你在开发BLE应用的时候,有时候会系统的功耗明显增加了,查看电量使用情况,蓝牙功耗占比非常高,好像低功耗是徒有虚名。使用 adb bugreport 获取的了系统信息,分析发现一个名叫 BluetoothRemoteDevices 的 WakeLock 锁持有时间非常长,导致系统进入不了休眠。分析源代码发现,在连接 BLE 设备的过程中,系统会持有 (Aquire) 这个 WakeLock ,直到连接上或者主动断开连接(调用 disconnect() )才会释放。如果BLE设备不在范围内,这个超时时间大约为30s,而这时你可能又要尝试重新连接,这个 WakeLock 有被重新持有,这样系统就永远不能休眠了。 **

  • 开发建议:对BLE设备连接,连接过程要尽量短,如果连接不上,不要盲目进行重连,否这你的电池会很快被消耗掉。这个情况,实际上对传统蓝牙设备连接也是一样

**Android作为中心设备,最多同时连接6个BLE外围设备(可能不同的设备在个数字不一样),超过6个就会连接不上,现在BLE设备越来越多,其实并不够用,所以开发过程中,需要特别谨慎使用

  • 开发建议:按照要求连接设备,如果设备使用完了,应该马上释放连接(调用:BluetoothGatt.close()),腾出系统资源给其他可能的设备连接。

题外话:谢谢大家观看,有不足之处欢迎大家一起讨论;码字不易,大家喜欢,麻烦点赞哦。


灵魂三问:

  • 有没有觉得技术得不到系统的提升,技术成长慢?
  • 有没面试懵逼,升职加薪难?
  • 有没有想过去大一点的世界看看?

有期望JAVA技术巩固的、Android知识进阶的、期望升职加薪的、Android面试技巧的大厂面试真题的;大家可以加我QQ哦:1070800492。我们一起学习,一起进步!

重要的事情说三遍:

  • 学习、挣钱、自由
  • 学习、挣钱、自由
  • 学习、挣钱、自由

疫情当下,唯有自强

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值