我正在开发一个应用程序,我可以在其中查找和配置BLE设备。我使用标准的Android BLE API,但最近我遇到了一些奇怪的问题。
当我打开我的应用程序时,BLE扫描工作正常。我正在使用扫描:
mBluetoothAdapter.startLeScan(mLeScanCallback); // for Kitkat and below
和
mBluetoothAdapter.getBluetoothLeScanner().startScan(mScanCallback); // for Lollipop and above
在Logcat中我收到以下消息(我想这对这个问题很重要):
D/BluetoothAdapter: onClientRegistered() - status=0 clientIf=5
在我的应用程序中,我还可以从我的BLE设备中读取某些特征(例如电池状态)。我使用以下方法连接到设备以在单独的片段中读取此特征:
mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(mMacAddress);
mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false, mGattCallback);
正确读取特征。在onCharacteristicRead
回调中,我还断开并关闭Gatt:
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
每次打开一个片段来读取一个特征(无论它是否是同一个设备),clientIf
值都会增加。我可以在LogCat中看到:
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=8
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=9
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=10
一切正常,直到clientIf
值等于10. BLE扫描停止查找任何设备,我无法连接到任何设备以读取任何特征等。而LogCat无限显示这些消息:
D/BluetoothGatt: unregisterApp() - mClientIf=0
D/BluetoothGatt: onClientRegistered() - status=133 clientIf=0
解决此问题的唯一方法是终止应用并将其重新启动,或通过手动关闭并重新启动蓝牙来重新启动蓝牙。我在某些设备上遇到过这个问题,比如Xperia Z1(Android KitKat)和Galaxy S4(Android Lollipop)。我无法在运行Android Marshmallow的Xperia Z3 Compact上重现这个问题...
我能做些什么吗?我已经尝试了多个“解决方案”,例如 - 从UI线程调用所有BLE方法并关闭/断开GATT,但没有任何帮助。我该如何解决?
答案 0 :(得分:10)
我会回答我自己的问题,因为它可以帮助有同样问题的人。
首先,在mClientIf
值达到10
后蓝牙崩溃,我无法解决问题。但是我找到了一个在我的情况下有用的解决方法。
即使我在第一个Fragment
中停止信标搜索并在另一个中开始特征读取,BLE API显然没有立即停止搜索,并且在打开下一个Fragment
系统之后创造另一个"客户"。
这就是为什么我需要在离开第一个Fragment
之后等待一段时间,然后再开始阅读另一个中的特征。
此方法在" new"的onCreateView
中调用。 Fragment
(使用postDelayed
帮助我解决问题):
private void getBatteryCharacteristic() {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
mBeaconBatteryStateReader = new BeaconBatteryStateReader(
BeaconDetailsActivity.this,
mBeacon.getMacAddress());
mBeaconBatteryStateReader.readBatteryState(BeaconDetailsActivity.this);
}
}, 100);
}
答案 1 :(得分:0)
关闭gatt对象是释放资源的正确方法。如果它仍然不起作用,则该特定手机上的Android存在错误。
为了尽量减少达到限制的机会,您可以确保每个设备永远不会有多个gatt对象。