这段时间在做低功耗蓝牙 (BLE) 应用的开发(并不涉及蓝牙协议栈)。总体感觉 Android BLE 还是不太稳定,开发起来也是各种痛苦。这里记录一些杂项和开发中遇到的问题及其解决方法,避免大家踩坑。本文说的问题有些没有得到官方文档的验证,不过也有一些论坛帖子的支持,也可以算是有一定根据。

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

BluetoothAdapter.startLeScan()

  1.  的时候,在 BluetoothAdapter.LeScanCallback.onLeScan()
    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: 
    * * * * * * * * * * * * * * * * * * * * * * 

onLeScan()

  1.  回调中只做尽量少的工作,可以把扫描到的设备,扔到另外一个线程中去处理,让  onLeScan() 尽快返回。  [  参考 帖子 ] 

BluetoothDevice.connectGatt()

  1.  或者 BluetoothGatt.connect() 等建立  BluetoothGatt

BluetoothGatt.disconnect()

  1.  来释放建立连接请求,然后处理下一个设备连接请求。  [  参考帖子 ] 

(read/write)Characteristic()

  1.  , (read/write)Descriptor() 和  readRemoteRssi() 都是异步操作。需要特别注意的是,同时只能有一个操作(有些贴这说只能同时有一个 writeCharacteristic() ,这个我并没有严格验证),也就是等上一个操作回调(例如  onCharacteristicWrite() 开发建议:把这写操作都封装成同步操作,一个操作回调之前,阻塞主其他调用。  [  参考帖子 ] 

BluetoothDevice.connectGatt()

  1.  ,  BluetoothGatt.connect() , BluetoothGatt.disconnect()

BluetoothGatt

  1.  的连接和断开请求,都通过发送消息到 Android 的主线程中,让主线程来执行具体的操作。例如创建一个  new Handler(context.getMainLooper()); ,把消息发送到这个  Handler中。  [  参考帖子 ] 

adb bugreport

  1.  获取的了系统信息,分析发现一个名叫 BluetoothRemoteDevices 的  WakeLock 锁持有时间非常长,导致系统进入不了休眠。分析源代码发现,在连接 BLE 设备的过程中,系统会持有 (Aquire) 这个  WakeLock ,直到连接上或者主动断开连接(调用  disconnect() )才会释放。如果BLE设备不在范围内,这个超时时间大约为30s,而这时你可能又要尝试重新连接,这个  WakeLock 开发建议:对BLE设备连接,连接过程要尽量短,如果连接不上,不要盲目进行重连,否这你的电池会很快被消耗掉。这个情况,实际上对传统蓝牙设备连接也是一样。  [  参考帖子 ] 
  2. Android 作为中心设备,最多只能同时连接 6 个 BLE 外围设备(可能不同的设备这个数字不一样),超过 6 个,就会连接不上了。现在 BLE 设备越来越多,其实并不够用,所以在开发的过程中,需要特别的谨慎使用。

BluetoothGatt.close()

  1.  ),腾出系统资源给其他可能的设备连接。  [  参考帖子 ] 

本文只是一些经验之谈,观点也比较琐碎。这里很多问题都看起来是蓝牙协议栈不完善导致的,或许在后面 Android 升级中会修复这些问题,我这里说的可能不适用了。