Android 6.0 Marshmallow BLE 连接问题

Posted

技术标签:

【中文标题】Android 6.0 Marshmallow BLE 连接问题【英文标题】:Android 6.0 Marshmallow BLE connectivity issues 【发布时间】:2016-10-30 11:57:55 【问题描述】:

我在使用 android 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);

这次改进没有改变。

在阅读了一些suggestions 并阅读了有关 BLE 连接问题的信息后,我发现了一些与三星 Galaxy S6 相关的问题,在one of those 中,他们提出了一系列解决 BLE 连接问题的步骤。关键之一是clear Bluetooth Share system app 数据。这样做,连接率立即增加了几乎 100% 的成功率。但是,如果您等待并使用其他一些 BLE 应用程序并连接到其他外围设备,问题迟早会出现。

Google Play 中有 some apps 试图解决这些 BLE 问题,他们基本上做的是:

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

虽然是清除蓝牙缓存的一种方式,但它需要设备root,这对于专业应用来说不是一个合理的解决方案。

我研究的所有私有 Android API 都没有帮助我解决这个问题,我发现的唯一一个类似的 API 是与问题无关的 enforce service discovery cache cleanup。

使用 BLE 数据包嗅探器,我发现 ADV_CONNECT_REQ 甚至没有从设备发送到外围设备,过了一会儿,Android 堆栈触发了 BluetoothGattCallback 中的 STATE_DISCONNECTED 事件。

我不完全知道为什么在某些 6.0 设备中会出现此问题,而在其他设备中则不会,因为蓝牙共享缓存似乎是问题所在。那里究竟存储了什么?只是以前连接/配对的设备?我是唯一遇到这个问题的人吗?如果不是,你们是怎么解决的?我不愿意指导最终用户如何清除蓝牙共享应用程序数据。

【问题讨论】:

在 S6 edge 上测试过,我可以确认,清除蓝牙共享缓存和数据帮助它连接,而无需传递 BluetoothDevice.TRANSPORT_LE 参数。我也不知道为什么会发生这种情况。在清除缓存之前,根本没有连接。 很高兴知道我不是唯一一个。感谢@CanCanbek 的反馈,希望有人可以帮助我们。 看了上面的内容,我明白了你的意思,6.0系统在S6 edge上,执行connectGatt()函数后,执行缓存操作,可以保证电话和通讯设备正常,不会有延误。是这个意思吗?@Can Canbek 我没有完美的解决方案,但发现调用 gatt dispose 并将其设置为 null 至少在一定程度上减少了这个问题。 我有一个 Moto X Play,BLE 设备发现在 Android 5.1.1 上运行良好。更新到 Android 6.0,它无法发现 BLE 设备。我也需要一个解决方案。在应用程序中,我调用 mBtAdapter.startLeScan(mLeScanCallback)。没有看到回调被调用。我从 Android Doc 中看到 startLeScan 方法在 API 级别 21 中已被弃用。 【参考方案1】:

有一个名为“removeBond”的隐藏方法。有时ble设备无法明确断开,此时需要调用remove bond。

来自here的代码

   //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(); 

此外,您可以使用隐藏方法“刷新”刷新 gatt 服务。最初刷新方法是用于更新 gatt 服务,但在某些意外断开连接的情况下,您可能需要刷新才能正确连接您的 gatt 服务。

How to programmatically force bluetooth low energy service discovery on Android without using cache

【讨论】:

【参考方案2】:

我的测试表明,这是 Android 蓝牙堆栈更普遍的问题,GATT 连接失败率约为 20%,而 ios 上仅为 2%。可以看我的详细测试结果here

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

但是长链接监督超时仍然不能解释第一次连接尝试的高失败率,或者短时间后连接丢失。

我发现不同的 BLE 外设在以相同的 Android 设备作为中心设备的情况下,GATT 连接失败率有很大差异。我的办公桌上有一台设备,我的 Google Pixel 3a 将以接近 100% 的速度成功连接,并保持连接数小时。我有另外两个外围设备,它们的连接失败率接近 20%,并且连接不能保持超过 15 秒。

【讨论】:

以上是关于Android 6.0 Marshmallow BLE 连接问题的主要内容,如果未能解决你的问题,请参考以下文章