完全断开蓝牙低功耗设备

Totally Disconnect a Bluetooth Low Energy Device

我使用 Android 中的 connectGatt() 方法连接到 BLE 设备。这很好用。

当我断开连接时,我使用以下内容:

private void disconnectDevice() {
    gatt.disconnect();
}

当我收到回调时,我会关闭。

private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        switch (newState) {
            case BluetoothProfile.STATE_CONNECTED:
                Log.d("BLED-GATT", "STATE_CONNECTED");
                setUIConnectionStatus("Discover services on device...", Color.YELLOW);
                checkEnableAddButton(simpleTrackEditText.getText().toString());
                gatt.discoverServices();
                break;
            case BluetoothProfile.STATE_DISCONNECTED:
                Log.d("BLED-GATT", "STATE_DISCONNECTED");
                setUIConnectionStatus("Not Connected!", Color.RED);
                gatt.close();
                break;
            default:
                Log.d("BLED-GATT", "STATE_OTHER");
        }
    }
}

执行完毕,调用后无法再控制设备disconnectDevice()。设备本身似乎认为它仍然处于连接状态,因为我无法将它置于广播可见性模式(如果它已经连接,则会发生这种情况)。但是,如果我终止应用程序并再次打开它,那么我可以将设备设置为广播模式。这告诉我应用程序未正确断开连接。

知道我错过了什么吗?

这完全符合逻辑,因为您在关闭 Gatt 之前没有断开连接。

public void disconnect() {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.disconnect();
    }

尝试在关闭您的 GATT

之前调用此方法

问题是我在扫描期间多次连接到同一设备,导致我的应用程序同时打开多个连接。添加 !isConnected() 解决了问题:

/**
 * Connects to the device. Does nothing if already connected.
 * @param macAddress the address of the device.
 */
private void connectDevice(String macAddress) {
    if (isConnected()) {
        return;
    }
    
    device = bluetoothAdapter.getRemoteDevice(macAddress);

    if (device == null) {
        showToast("Device not available");
    } else {
        showToast("Connecting...");
        gatt = device.connectGatt(this, true, gattCallback);
    }
}

我遇到了同样的问题,我发现了两个可能的根本原因如下: 1. 与@nilsi 的回答相同,在一次扫描中多次连接到同一设备。 → 通过 lock & List 解决 2. 在一次扫描中连接到设备并且没有得到 onConnectionStateChange,比我再次扫描,它导致第二次连接到同一设备。 → 通过在调用 device.connectGatt() 时保留 BluetoothGatt 对象解决,并在扫描前调用 object.disconnect()、object.close()。

我的测试 phone 已有 4 年历史,所以有时 return onConnectionStateChange 需要 20 多秒....

如前所述,问题是多次调用connectGatt引起的。这些调用中的每一个都会创建一个新的 BluetoothGatt 实例,并且它们都保持活动状态,而您只有最后一个。考虑到有时需要多次调用 connectGatt,我只保留它 returns 的所有实例,并在完成后对所有实例调用 disconnect/close。这立即解决了断开连接问题

private val gattInstances = LinkedList<BluetoothGatt>()


fun connect() {
    bluetoothGatt = device?.connectGatt(
        context,
        false, gattCallback, TRANSPORT_LE
    )
    bluetoothGatt?.let { gattInstances.add(it) }
}

fun finish() {
    bluetoothGatt?.close()
    while (gattInstances.isNotEmpty()) {
        gattInstances.pop().apply {
            disconnect()
            close()
        }
    }
}