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

Android stops finding BLE devices: 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)。我无法在 Xperia Z3 Compact 上重现此问题 运行 Android Marshmallow...

我能做些什么吗?我已经尝试了多个 "solutions",例如 - 从 UI 线程和 closing/disconnecting GATT 调用所有 BLE 方法,但没有任何帮助。我该如何解决?

关闭gatt对象才是释放资源的正确方式。如果它仍然不起作用,则 Android 中的特定 phone.

中存在错误

为了尽量减少达到限制的可能性,您可以确保每台设备的 gatt 对象永远不会超过一个。

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

首先,我无法解决 mClientIf 值达到 10 后蓝牙崩溃的问题。但是,我找到了一种对我的情况有帮助的解决方法。

即使我在第一个 Fragment 中停止信标搜索并在另一个中开始特征读取,BLE API 显然并没有立即停止搜索并在打开下一个 Fragment 系统正在创建另一个 "client"。

这就是为什么我需要在离开第一个 Fragment 和开始阅读另一个特征之前等待一段时间。

此方法在 "new" FragmentonCreateView 中调用(使用 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);
    }