Android 4.3蓝牙低功耗不稳定


189

我目前正在开发将使用低功耗蓝牙的应用程序(在Nexus 4上进行测试)。在开始使用Android 4.3中的官方BLE API之后,我注意到,第一次连接设备后,我很少能够再次成功连接到该设备或任何其他设备或与之通信。

遵循此处的指南,我可以成功连接到设备,扫描服务和特征以及读取/写入/接收通知,而不会出现任何问题。但是,在断开连接并重新连接后,我通常无法扫描服务/特性或无法完成读取/写入。我在日志中找不到任何可以指示这种情况发生的原因。

一旦发生这种情况,我必须先卸载应用程序,禁用蓝牙并重新启动手机,然后手机才能再次开始工作。

每当设备断开连接时,请确保在BluetoothGatt对象上调用close()并将其设置为null。有什么见解吗?


编辑:
日志转储:对于这些日志,我扎根了手机,并提高了/etc/bluetooth/bt_stack.conf中相关项目的跟踪级别

成功连接 -重新启动手机并安装应用程序后的首次尝试。我能够连接,发现所有服务/特征以及进行读/写。

尝试失败1-这是与上面的成功连接断开连接后的下一次尝试。看来我能够发现特征,但是第一次读取尝试返回了一个空值,此后不久就断开了连接。

尝试失败2-我什至无法发现服务/特征的示例。


编辑2:
我尝试连接的设备基于TI的CC2541芯片。我获得了TI SensorTag(也基于CC2541)来玩耍,并发现TI 昨天为SensorTag 发布了一个Android应用。但是,这个程序有同样的问题。我在其他两个Nexus 4上进行了测试,结果相同:第一次或第二次成功连接SensorTag,但此后(根据日志)未能发现服务,从而导致各种崩溃。我开始怀疑这块特定的芯片是否有问题?


请从启动开始发布手机的完整日志,直到遇到问题为止。
AAnkit

3
我正在使用装有泄漏的Google版本Android 4.3的Samsung Galaxy S4;在无数次连接/断开连接之后,当我发现服务时,我将随机获得129(GATT_INTERNAL_ERROR)并获得状态为133(GATT_ERROR)的onConnectionStateChange,状态= BluetoothProfile.DEVICE_DISCONNECTED。
13年

1
一两次,我在短时间内获得了多个状态129和133回调,并且在重新启动设备之前,BluetoothGattCallback从未收到任何回调(但是扫描很好)。
13年

1
忘了说,我正在使用TI芯片对大约十种设备进行测试(对不起,我不知道他们的型号),而使用Nordic芯片的是其中一台设备。具有Nordic芯片的设备从不报告错误。(尽管不足以证明问题是TI所特有的)
reTs

1
我可以确认此问题在Samsung Galaxy S5(G900VVRU2BOG5G900VVRU2BOA8生成版本)上仍然存在。如果我从“设置”>“应用程序管理器” >>“所有” >>“蓝牙”中清除数据,则该功能暂时可用。
IronBlossom,2015年

Answers:


184

重要的实施提示

(由于Android操作系统的更新,也许其中的某些提示不再是必需的。)

  1. 某些设备(如带有Android 4.3的Nexus 4)需要使用现有gatt实例进行45秒以上的连接。解决方法:始终在断开连接时关闭gatt实例,并在每次连接时创建一个新的gatt实例。
  2. 别忘了打电话 android.bluetooth.BluetoothGatt#close()
  3. 在其中启动一个新线程 onLeScan(..),然后连接。原因:BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)如果LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)在带有Android 4.3的Samsung Galaxy S3的同一线程中内部调用,则始终会失败(至少对于构建JSS15J.I9300XXUGMK6)
  4. 大多数设备过滤广告
  5. 最好不要 android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) 与该参数一起使用以过滤某些服务UUID,因为它在带有Android 4.3的Samsung Galaxy S3中已完全损坏,并且通常不适用于128位UUID
  6. 加特总是一次能处理一个命令。如果几个命令接一个被短暂调用,则由于gatt实现的同步性,第一个命令被取消
  7. 我什至经常在配备Android 5的现代设备上看到Wifi干扰蓝牙,反之亦然。不得已时,请关闭wifi来稳定蓝牙。

初学者教程

对于新手来说,一个不错的入门点可以是此视频教程:为Android开发蓝牙智能应用程序http://youtu.be/x1y4tEHDwk0

操作系统更新现已解决了下面描述的问题和解决方法

解决方法:这样做可以“稳定”我的应用程序...

  1. 我为用户提供了“重启蓝牙”设置。如果启用了该设置,我会在某些时候重启蓝牙,这表明BLE堆栈的开始变得不稳定。例如,如果startScan返回false。如果serviceDiscovery失败,这也可能是个好主意。我只是关闭蓝牙然后再打开。
  2. 我提供了另一个设置“关闭WiFi”。如果启用了该设置,则我的应用在运行时会关闭Wifi(然后将其重新打开)

解决方法是基于以下经验...

  • 在大多数情况下,重启蓝牙有助于解决BLE问题
  • 如果关闭Wifi,则BLE堆栈会变得更加稳定。但是,它在打开wifi的大多数设备上也可以正常工作。
  • 如果您关闭Wifi,则在大多数情况下,重新启动蓝牙可完全恢复BLE堆栈,而无需重新启动设备。

33
Google,您现在必须解决此问题。这种解决方法(我确实加上了它是因为它确实有效)是荒谬的。
克里斯·赫伯特

4
有时,服务发现将以状态0成功(假设没有问题),但是特征读取将产生NULL值,因为它实际上没有真正连接或未发现特征(我在日志中看到此信息:11-01 18:37: 32.131:WARN / BluetoothGatt(20119):未处理的异常:java.lang.NullPointerException)
Lo-Tan

2
@ Lo-Tan我总是在发现服务后检查是否已包含我期望的服务。您也无法确定服务发现是否会产生任何结果。有时我没有收到回调。因此,我将超时用于服务发现。
OneWorld

2
我的经验是:如上文第2段所述,在关闭Gatt客户端后,三星S3(4.3)成功重新连接;使用Nexus 4和7(4.4.2),即使断开连接,即使重新启动BL适配器,我也无法重新连接,但2分钟后可以自动重新连接
Konstantin Konopko 2014年

1
任何人都可以确认android.bluetooth.BluetoothGatt是否只能按PER DEVICEPER PROCESSPERIOD处理一个挂起的GATT操作(即:在所有进程中)。我想这是每个设备,但是这个问题是如此糟糕,以至于如果不是这样的话我也不会感到惊讶。如果限制仅是PER DEVICE,则能够处理多个同时操作的OS /设备可以证明该问题完全是由于OS处理每个进程的BluetoothAdapter实例中某些较幼稚的天真的实现(我认为是所有流程中的一个单例)。
swooby

18

关闭WIFI:

我也可以确认,关闭WIFI可使蓝牙4.0更稳定,尤其是在Google Nexus(我有Nexus 7)上。

问题

是我开发的应用程序需要两个WIFI和连续蓝牙LE扫描。因此关闭WIFI对我来说是没有选择的。

此外,我已经意识到,持续的蓝牙LE扫描实际上可以终止WIFI连接,并使WIFI适配器在BLE扫描打开之前无法重新连接到任何WIFI网络。(我不确定移动网络和移动互联网)。
这肯定发生在以下设备上:

  • Nexus 7
  • 摩托罗拉摩托G

但是,启用WIFI的BLE扫描在以下方面似乎相当稳定:

  • 三星S4
  • HTC One

我的解决方法

扫描BLE短时间3-4秒,然后关闭扫描3-4秒。然后再次打开。

  • 显然,当我连接到BLE设备时,我总是关闭BLE扫描。
  • 当我与设备断开连接时,我将重新启动BLE(先关闭适配器然后再打开)以重置堆栈,然后再次开始扫描。
  • 发现servicescharacteristics失败时,我也会重置BLE 。
  • 当我从应用程序应连接的设备获取广告数据时(假设说500次却无法连接-那大约是5-10秒的广告时间),我再次重置BLE。

您说设备断开连接后我重新启动BLE。假设,如果用户正在通过蓝牙连接传输文件。然后,您将随时导致蓝牙传输失败。
Rahul Rastogi

1
“先关闭适配器再打开”是什么意思?
玛丽安(MarianPaździoch)2015年

我同意,WiFi和蓝牙一起被杀死在摩托G.应用性能
Nigilan

@MarianPaździoch,通过“先关闭适配器然后再打开” @ benka表示BluetoothAdapter
Anup

9

确保您的Nexus已与设备配对。我无法验证通讯是否正常,但是您无需重新启动就能连接多个。似乎第一个连接不需要配对,但随后的所有尝试都需要配对。

我将在几天内测试服务发现和gatt读写请求而无需重新启动,以更新此答案。

编辑:事实证明,我正在测试开发固件版本(我们的传感器),如果未配对会导致问题。我们最新的生产固件版本可在2540和2541上正常运行。

编辑:我确实注意到,在Nexus 7 2013上,关闭WiFi后连接更加稳定。我想知道这是否对其他人有帮助。

编辑:我似乎已经与配对倒退。未配对时,一切正常。配对后,我遇到与OP完全相同的症状。只是不知道这是否与我们的固件或Android BLE API有关。如果进行测试,请小心,因为一旦配对,由于这篇文章 3b中解释的错误,您可能无法取消配对。


我一直在连接和重新连接CC2541设备,而无需进行任何手动配对或重新启动。
dgel

我认为,没有必要配对。官方文档也不会评论配对。我也可以执行写入,读取,特征更改通知而无需任何配对。但是,只是短时间。现在又摇摇欲坠... SAMSUNG BLE SKD v2.0也不需要配对,并且运行良好。
OneWorld

3
我可以确认,关闭Wifi后会更稳定。每个人都应该尝试。
OneWorld

1
是否需要配对取决于设备的实现。nrf8002设备需要配对,三星2.0和1.2 API均支持此功能。似乎官方的api支持在配对方面有问题,因为在我配对ble设备之后,似乎无法取消配对!
克里斯·赫伯特

2
我因无法配对而无法解决。1)进入bt菜单,选择取消配对,从该区域移除ble设备或将其断电,在bt菜单中选择ble设备,它将尝试配对并失败,然后重置蓝牙。重置后,设备将无法配对。
克里斯·赫伯特

7

在某些模型中,存在缺陷:https : //code.google.com/p/android/issues/detail?id=180440

另一方面,在我的情况下,问题是在onDestroy方法中未正确关闭我的连接。正确关闭后,对我来说不存在问题,无论是否打开或关闭wifi。

btGatt.disconnect();
btGatt.close();

为什么有close必要?
IgorGanapolsky '17

3
当您想多次连接蓝牙时,正确的关闭步骤是“关键”。以我的经验,如果您在单独的UNBOUND服务中运行Ble连接,则效果最佳,因此您可以手动启动和停止它。然后调用mConnectedGatt.disconnect(); ble_device = null; 在您的inDestroy()中。就我而言,此模式可以稳定运行而不会出现问题。
medTech '18

4

我面临着类似的问题。我的解决方法是

if (Build.VERSION.SDK_INT >= 23) {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}

&断开连接后调用关闭。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.