问题 Android停止查找BLE设备:onClientRegistered() - status = 133 clientIf = 0


我正在开发一个应用程序,我可以在其中查找和配置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,但没有任何帮助。我该如何解决?


2894
2017-09-22 18:21


起源



答案:


我会回答我自己的问题,因为它可以帮助有同样问题的人。

首先,我无法解决蓝牙崩溃后的问题 mClientIf 达到了价值 10。但是我找到了一个在我的案例中有用的解决方法。

即使我在第一次停止信标搜索 Fragment 并且开始特性在另一个中读取,BLE API显然没有立即停止搜索并且在打开下一个之后 Fragment 该系统正在创造另一个“客户”。

这就是我离开第一个后需要等待一段时间的原因 Fragment 在开始阅读另一个特征之前。

调用此方法 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);
    }

9
2017-09-26 17:01



我有一个类似的问题,对我来说,在断开连接和扫描之间增加一点延迟也解决了这个问题。谢谢! - Tijn
我找到了和你一样的解决方案。细节: github.com/googlesamples/android-BluetoothLeGatt/issues/44 - Sam Protsenko


答案:


我会回答我自己的问题,因为它可以帮助有同样问题的人。

首先,我无法解决蓝牙崩溃后的问题 mClientIf 达到了价值 10。但是我找到了一个在我的案例中有用的解决方法。

即使我在第一次停止信标搜索 Fragment 并且开始特性在另一个中读取,BLE API显然没有立即停止搜索并且在打开下一个之后 Fragment 该系统正在创造另一个“客户”。

这就是我离开第一个后需要等待一段时间的原因 Fragment 在开始阅读另一个特征之前。

调用此方法 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);
    }

9
2017-09-26 17:01



我有一个类似的问题,对我来说,在断开连接和扫描之间增加一点延迟也解决了这个问题。谢谢! - Tijn
我找到了和你一样的解决方案。细节: github.com/googlesamples/android-BluetoothLeGatt/issues/44 - Sam Protsenko


关闭gatt对象是释放资源的正确方法。如果它仍然无法正常工作,那特定手机上的Android就会出现错误。

为了最大限度地减少达到限制的机会,您可以确保每个设备永远不会有多个gatt对象。


0
2017-09-22 20:04