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 连接问题的主要内容,如果未能解决你的问题,请参考以下文章
Android 6.0 (MarshMallow) 上的 HttpURLConnnection 请求失败
如何在 Android 6.0 Marshmallow 中访问相机?
如何以编程方式打开 Android 6.0 (Marshmallow) 上特定应用的权限屏幕?
Android 6.0 Marshmallow BLE 连接问题