Android ble蓝牙问题

 

(1)蓝牙回调
安卓4.4的蓝牙回调是在异步线程中(不在主线程),若要在蓝牙回调中执行更新界面的操做,记得切换到主线程去操做html

 

 

(2)三星手机兼容性问题
connectGatt()方法在某些三星手机上只能在UI线程调用。android

备注:三星的手机是connet和disconnet还有connectGatt都要在UI线程中操做缓存

 

 

(3)Android L 新API
Android L换了一套扫描设备的API:BluetoothLeScanner.startScan(List, ScanSettings, ScanCallback)异步

 

 

(4)Android M新的权限(android 6.0 动态权限)
Android M中必须拥有定位权限才能扫描BLE设备ide

 

(4)链接不断开的问题
别的BLE程序非法保留链接的设备可能会致使链接不能断开oop

 

(5)异步问题
读写Characteristic、Descriptor等几乎全部BLE操做结果都为异步返回,若不等待上一次操做结果返回就执行下一次操做,极可能致使操做失败或者操做无效。onDescriptorWrite()返回的线程与写入线程为同一个线程,别的操做通常在不一样的线程回调。ui

 

 

(6)设备缓存
Android会对链接过的BLE设备的Services进行缓存,若设备升级后Services等有改动,则程序会出现通信失败。此时就得刷新缓存,可是刷新缓存的方法并无开放,这里只能使用反射来调用BluetoothGatt类中的refresh()方法:google

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

 

(7)扫描设备
startLeScan(UUID[], BluetoothAdapter.LeScanCallback)spa

在Android4.4及如下手机中彷佛只支持16位的短UUID,不支持128位完整的UUID。线程

(9)任何出错,超时,用完就立刻调用Gatt.disconnect(), Gatt.close()。

(10)从bindService 到 onServiceConnected 这个回调花费时间较长, onServiceConnected 这个回调极可能在 MainActivity onResume以后才执行, 因此不要期望onResume里去执行扫描,由于此时serviceConnected 回调都还没有执行

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

(12) 屡次扫描蓝牙,在华为荣耀,魅族M3 NOTE 中有的机型,会发现屡次断开–扫描–断开–扫描… 会扫描不到设备,此时须要在断开链接后,不能当即扫描,而是要先中止扫描后,过2秒再扫描才能扫描到设备。

(13)扫描尽可能不要放在主线程进行,能够放入子线程里。否则有些机型会出现 do too many work in main thread.

(14)设备的gatt在不用时要及时关闭,系统支持的链接句柄数是有限的,当达到上限后没法再创建新的链接了。

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

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

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

(18)对蓝牙设备的操做不能并行,只能串行,即每次都要在收到上一个操做的回调后才能继续下一个操做。可是断开链接例外,断开链接要立刻closeGatt,不用等任务队列中的其余操做了。并且要给全部正在执行或者准备执行的任务都cancel。

(19)有时候蓝牙协议栈出现异常可能收不到回调,因此咱们要对每一个操做作超时检查,不然后面的全部操做都被阻塞了。

(20)对于超时的任务,最好closeGatt,下次从新链接的时候重开一个gatt。

(21)蓝牙链接可能不稳定,最好支持失败自动重试机制,尤为是链接和发现服务,由于80%的问题都发生在创建链接和发现服务的时候,并且这一块也是最耗时的。

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

(23)

在  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() 尽快返回。  [  参考帖子 ] 

(24)BLE 设备的创建和断开链接的操做,例如 BluetoothDevice.connectGatt() ,  BluetoothGatt.connect() , BluetoothGatt.disconnect() 等操做最好都放在主线程中,不然你会遇到不少意想不到的麻烦。 

开发建议:对  BluetoothGatt 的链接和断开请求,都经过发送消息到 Android 的主线程中,让主线程来执行具体的操做。例如建立一个  new Handler(context.getMainLooper()); ,把消息发送到这个  Handler中。  [  参考帖子 ] 

 (25)

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

开发建议:对BLE设备链接,链接过程要尽可能短,若是链接不上,不要盲目进行重连,否这你的电池会很快被消耗掉。这个状况,实际上对传统蓝牙设备链接也是同样。  [  参考帖子 ] 

(26)

Android 做为中心设备,最多只能同时链接 6 个 BLE 外围设备(可能不一样的设备这个数字不同),超过 6 个,就会链接不上了。如今 BLE 设备愈来愈多,其实并不够用,因此在开发的过程当中,须要特别的谨慎使用。

开发建议:按照须要链接设备,若是设备使用完了,应该立刻释放链接(调用 BluetoothGatt.close() ),腾出系统资源给其余可能的设备链接。  [  参考帖子 ] 

相关文章
相关标签/搜索