Android ble蓝牙问题

声明:本文摘抄自博客园

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

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

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

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

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

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

(6)设备缓存Android会对连接过的BLE设备的Services进行缓存,若设备升级后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");
 }

(7)扫描设备

startLeScan(UUID[], BluetoothAdapter.LeScanCallback)

在Android4.4及以下手机中似乎只支持16位的短UUID,不支持128位完整的UUID。
(9)任何出错,超时,用完就马上调用Gatt.disconnect() ,Gatt.close()
(10)从bindServiceonServiceConnected这个回调花费时间较长,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 ,也不要下次复用之前的gattreconnect ,因为有的手机上重连可能会存在问题,比如重连后死活发现不了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()
),腾出系统资源给其他可能的设备连接。 [ 参考帖子 ]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 初识低功耗蓝牙 Android 4.3(API Level 18)开始引入Bluetooth Low Energy...
    JBD阅读 112,448评论 46 342
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • BLE 与经典蓝牙的区别 BLE 的 Kotlin 下实践 BluetoothGattCallback 不回调异常...
    chauI阅读 10,716评论 1 7
  • 提笔想写点什么的念想一直在脑海中盘旋,但就是没有下定决心提笔,总是在给自己找各种借口去原谅自己没有写作!! ...
    晨若若曦阅读 452评论 7 3
  • 秋天终于缓缓来了 在八月的尾巴里 我才理解了一次夏天的美 那度过的最后几天 活成了生命最深刻的烙印 夏天随着降雨一...
    艾拉夫阅读 252评论 0 0