安卓6.0棉花糖蓝牙连接问题

15

我在使用安卓6.0的时候,发现了一些严重的与蓝牙低功耗有关的问题。其中一个冲突设备就是这个:

DEVICE INFO:
Name:         Samsung Galaxy SV  
Model number: SM-G900V  
Android vers: 6.0.1  
Patch level:  May 1, 2016  
Hard. vers:   G900V.05  

如果我基于连接和断开应用程序与BLE外设进行一些压力测试,成功率几乎只有50%。

阅读Android的最新文档,他们建议在connectGatt方法的最后一个参数中指定传输模式,以强制执行BLE传输连接而不是BR / EDR:

device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);

这项改进没有任何变化。

在遵循一些建议并阅读有关BLE连接问题的文章后,我发现三星Galaxy S6存在几个相关问题,在其中一个中,他们建议采取一系列步骤来解决BLE连接问题。 其中关键步骤是清除蓝牙共享系统应用程序数据。 这样做,连接成功率几乎立即增加了近100%。 但是,如果您等待并使用其他BLE应用程序并连接到其他外围设备,则问题迟早会重新出现。

在Google Play中有一些应用程序尝试修复这些BLE问题,它们基本上所做的是:

/system/bin/rm -r /data/misc/bluetoothd/*
/system/bin/rm -r /data/misc/hcid/*

尽管这是清除蓝牙缓存的一种方法,但它需要设备被root,这对于专业应用来说并不是一个合理的解决方案。我研究过的私有Android API都无法帮助我解决这个问题,唯一类似的是强制服务发现缓存清理,但与该问题无关。
使用BLE数据包嗅探器,我发现设备甚至没有发送ADV_CONNECT_REQ到周边设备,一段时间后,Android堆栈在BluetoothGattCallback中触发了STATE_DISCONNECTED事件。
我不知道为什么某些6.0设备会出现这个问题,而其他设备则不会,因为蓝牙共享缓存似乎是问题所在。那里到底存储了什么?只是之前连接/配对的设备吗?我是唯一遇到这个问题的人吗?如果不是,你们怎么解决的?我不想指导最终用户如何清除蓝牙共享应用程序数据。

在S6 edge上测试过了,我可以确认,清除蓝牙共享缓存和数据有助于连接,而无需传递BluetoothDevice.TRANSPORT_LE参数。我对为什么会发生这种情况感到困惑。在清除缓存之前,根本无法连接。 - Can Canbek
很高兴知道我不是唯一一个遇到这个问题的人。感谢@CanCanbek的反馈,希望有人能够帮助我们。 - GoRoS
我已经阅读了上述内容,我理解你的意思大致是,在S6 edge的6.0系统中,在执行connectGatt()函数后,进行缓存操作可以确保手机和通信设备之间的正常连接,从而避免延迟。这是否是你的意思?@Can Canbek - amibition
我没有完美的解决方案,但发现调用gatt dispose并将其设置为null至少在一定程度上减少了这个问题。 - user2107373
当使用这些有问题的移动设备时,在BLE扫描结果中是否可靠地显示您的BLE外围设备?我过去在扫描中遇到了找不到外围设备以及连接外围设备的间歇性故障。我最糟糕的设备是三星Galaxy Tab S2和三星Xcover3。我们通过使我们的外围设备调整其BLE发射功率,直到建立连接来解决了三星Xcover3上的问题。一些设备在特定的RSSI范围内才能发现BLE广播包。这已经是漫长而痛苦的过程了。 - Mark Ch
显示剩余2条评论
2个回答

0

我的测试表明,这是与Android蓝牙堆栈相关的普遍问题,GATT连接失败率约为20%,而iOS仅为2%。您可以在这里查看我的详细测试结果。

问题的一部分是Android BLE链路监督超时在Android 4.3-9中硬编码为20秒(在Android 10上为5秒,在iOS上为750毫秒),因此,如果连接丢失,大多数Android设备将在20秒内无声地失败以重新连接。

但长时间的链路监督超时仍然无法解释第一次连接尝试的高故障率或在短时间内丢失连接。

我发现不同的BLE外围设备在扮演中心角色的相同Android设备上具有非常不同的GATT连接故障率。我桌子上有一个设备,我的Google Pixel 3a将以接近100%的速率成功连接,并保持该连接数小时。 我还有两个其他外围设备,其连接失败率接近20%,并且连接永远无法超过15秒。


0

有一个名为“removeBond”的隐藏方法。有时,蓝牙设备无法清除连接,这种情况下需要调用remove bond。

代码来自这里

   //remove authrization 
   Method method = null; 
   try { 
       method = gatt.getDevice().getClass().getMethod("removeBond", (Class[]) null); 
       method.invoke(gatt.getDevice(), (Object[]) null); 
   } catch (Exception e) { 
       e.printStackTrace(); 
   }        
   gatt.disconnect(); 

此外,您可以使用隐藏方法“refresh”刷新gatt服务。最初,刷新方法用于更新gatt服务,但在某些意外断开连接的情况下,您可能需要刷新以正确连接您的gatt服务。 如何在Android上以编程方式强制执行蓝牙低功耗服务发现而不使用缓存

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接