Android BLE 开发常见问题总结
2016-08-08 15:06
337 查看
本文手机了 截止2016年8月笔者开发BLE以及网络上面的一些BLE开发经验,大家共同学习,共同进步。
这段时间在做低功耗蓝牙 (BLE) 应用的开发(并不涉及蓝牙协议栈)。总体感觉 Android BLE 还是不太稳定,开发起来也是各种痛苦。这里记录一些杂项和开发中遇到的问题及其解决方法,避免大家踩坑。本文说的问题有些没有得到官方文档的验证,不过也有一些论坛帖子的支持,也可以算是有一定根据。
Android 从 4.3(API Level 18) 开始支持低功耗蓝牙,但是只支持作为中心设备 (Central) 模式,这就意味着 Android 设备只能主动扫描和链接其他外围设备 (Peripheral)。从Android 5.0(API Level 21)开始两种模式都支持。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): * * * * * * * * * * * * * * * * * * * * * *
开发建议:在
在使用
Gatt 连接请求。如果前面的设备连接失败了,后面的设备请求会被永远阻塞住,不会有任何连接回调。
开发建议:如果要对多个设备发起连接请求,最好是有一个同一个的设备连接管理,把发起连接请求序列化起来。前一个设备请求建立连接,后面请求在队列中等待。如果连接成功了,就处理下一个连接请求。如果连接失败了(例如出错,或者连接超时失败),就马上调用
对 BluetoothGatt 操作
开发建议:把这写操作都封装成同步操作,一个操作回调之前,阻塞主其他调用。 [ 参考帖子 ]
BLE 设备的建立和断开连接的操作,例如
开发建议:对
Android 的主线程中,让主线程来执行具体的操作。例如创建一个
如果你在开发 BLE 应用的时候,有时候会发现系统的功耗明显增加了,查看电量使用情况,蓝牙功耗占比非常高,好像低功耗是徒有虚名。使用
BLE 设备的过程中,系统会持有 (Aquire) 这个
开发建议:对BLE设备连接,连接过程要尽量短,如果连接不上,不要盲目进行重连,否这你的电池会很快被消耗掉。这个情况,实际上对传统蓝牙设备连接也是一样。 [ 参考帖子 ]
Android 作为中心设备,最多只能同时连接 6 个 BLE 外围设备(可能不同的设备这个数字不一样),超过 6 个,就会连接不上了。现在 BLE 设备越来越多,其实并不够用,所以在开发的过程中,需要特别的谨慎使用。
开发建议:按照需要连接设备,如果设备使用完了,应该马上释放连接(调用
对于android M系统,需要动态申请LOCATION权限,对于第三方应用需要打开GPS定位,否则会搜索不到设备。
这段时间在做低功耗蓝牙 (BLE) 应用的开发(并不涉及蓝牙协议栈)。总体感觉 Android BLE 还是不太稳定,开发起来也是各种痛苦。这里记录一些杂项和开发中遇到的问题及其解决方法,避免大家踩坑。本文说的问题有些没有得到官方文档的验证,不过也有一些论坛帖子的支持,也可以算是有一定根据。
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()尽快返回。 [ 参考帖子 ]
在使用
BluetoothDevice.connectGatt()或者
BluetoothGatt.connect()等建立
BluetoothGatt连接的时候,在任何时刻都只能最多一个设备在尝试建立连接。如果同时对多个蓝牙设备发起建立
Gatt 连接请求。如果前面的设备连接失败了,后面的设备请求会被永远阻塞住,不会有任何连接回调。
开发建议:如果要对多个设备发起连接请求,最好是有一个同一个的设备连接管理,把发起连接请求序列化起来。前一个设备请求建立连接,后面请求在队列中等待。如果连接成功了,就处理下一个连接请求。如果连接失败了(例如出错,或者连接超时失败),就马上调用
BluetoothGatt.disconnect()来释放建立连接请求,然后处理下一个设备连接请求。 [ 参考帖子 ]
对 BluetoothGatt 操作
(read/write)Characteristic(),
(read/write)Descriptor()和
readRemoteRssi()都是异步操作。需要特别注意的是,同时只能有一个操作(有些贴这说只能同时有一个
writeCharacteristic(),这个我并没有严格验证),也就是等上一个操作回调(例如
onCharacteristicWrite())以后,再进行下一个操作。
开发建议:把这写操作都封装成同步操作,一个操作回调之前,阻塞主其他调用。 [ 参考帖子 ]
BLE 设备的建立和断开连接的操作,例如
BluetoothDevice.connectGatt(),
BluetoothGatt.connect(),
BluetoothGatt.disconnect()等操作最好都放在主线程中,否则你会遇到很多意想不到的麻烦。
开发建议:对
BluetoothGatt的连接和断开请求,都通过发送消息到
Android 的主线程中,让主线程来执行具体的操作。例如创建一个
new Handler(context.getMainLooper());,把消息发送到这个
Handler中。 [ 参考帖子 ]
如果你在开发 BLE 应用的时候,有时候会发现系统的功耗明显增加了,查看电量使用情况,蓝牙功耗占比非常高,好像低功耗是徒有虚名。使用
adb bugreport获取的了系统信息,分析发现一个名叫
BluetoothRemoteDevices的
WakeLock锁持有时间非常长,导致系统进入不了休眠。分析源代码发现,在连接
BLE 设备的过程中,系统会持有 (Aquire) 这个
WakeLock,直到连接上或者主动断开连接(调用
disconnect())才会释放。如果BLE设备不在范围内,这个超时时间大约为30s,而这时你可能又要尝试重新连接,这个
WakeLock有被重新持有,这样系统就永远不能休眠了。
开发建议:对BLE设备连接,连接过程要尽量短,如果连接不上,不要盲目进行重连,否这你的电池会很快被消耗掉。这个情况,实际上对传统蓝牙设备连接也是一样。 [ 参考帖子 ]
Android 作为中心设备,最多只能同时连接 6 个 BLE 外围设备(可能不同的设备这个数字不一样),超过 6 个,就会连接不上了。现在 BLE 设备越来越多,其实并不够用,所以在开发的过程中,需要特别的谨慎使用。
开发建议:按照需要连接设备,如果设备使用完了,应该马上释放连接(调用
BluetoothGatt.close()),腾出系统资源给其他可能的设备连接。 [ 参考帖子 ]
对于android M系统,需要动态申请LOCATION权限,对于第三方应用需要打开GPS定位,否则会搜索不到设备。
相关文章推荐
- 一个三年Android开发的总结 - 常见数据库问题总结
- Android开发常见问题总结
- android 蓝牙开发常见问题总结
- Android 开发常见问题总结
- android开发步步为营之73:Android开发常见问题技术点总结之二
- Android常见问题及开发经验总结(四)
- Android常见问题及开发经验总结(三)
- Android 开发常见问题总结
- Android Edittext 开发常见问题总结(焦点、输入、键盘弹出等)
- Android开发常见问题总结
- android开发步步为营之56:Android开发常见问题技术点总结之一
- android之开发总结,常见问题,细节问题,用户体验
- Android常见问题及开发经验总结
- Android 音视频开发中常见基础问题总结
- android开发常见问题总结
- Android常见问题及开发经验总结(二)
- Android 开发中一些常见问题的总结汇总
- android 蓝牙开发常见问题总结
- android环境搭建常见问题总结
- Android手机常见问题以及解决办法[非开发]