【问题标题】:Totally Disconnect a Bluetooth Low Energy Device完全断开蓝牙低功耗设备
【发布时间】:2016-06-29 10:23:28
【问题描述】:

我在 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()之后我不能再控制设备了。设备本身似乎认为它仍然处于连接状态,因为我无法将其置于广播可见性模式(如果它已经有连接,则会发生这种情况)。但是,如果我终止应用程序并再次打开它,那么我可以将设备设置为广播模式。这告诉我应用程序未正确断开连接。

知道我在这里错过了什么吗?

【问题讨论】:

  • 连接ble设备后是否停止扫描设备?我有一个类似的问题,即使在断开连接后手机仍然连接到 ble 芯片。问题是我在成功连接后从未调用过 mScanner.stopScan(mScanCallback)。
  • 谢谢,但是我会在连接成功后调用 stopScan。

标签: android bluetooth iot bluetooth-lowenergy


【解决方案1】:

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

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

尝试在关闭GATT之前调用此方法

【讨论】:

  • 我在关闭前断开连接,在断开连接时调用回调。这意味着我在拨打close() 时已经断开了它?你的答案只是在我的代码中添加一个空检查?
  • 不不,事实上你必须调用disconnect方法,否则它只会关闭Gatt而不断开!试试吧
【解决方案2】:

问题是我在扫描期间多次连接到同一设备,导致我的应用程序同时打开了许多连接。添加!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);
    }
}

【讨论】:

  • isConnected() 是否返回某种您跟踪的私有变量?你能详细说明一下吗...?谢谢!
  • 不记得了,但我认为那只是我制作的一种实用方法。检查gatt 是否为空,如果是,那么我确定已经没有连接。我还应该在onConnectionStateChange 中将gatt 设置为null 我认为
  • 根据规范,这不是对等方的正确行为。当一个对等体接收到一个连接事件时,它应该停止广播。由于许多 BTLE 设备表现不佳(Android API 也是如此),因此我忽略了从已连接设备接收到的任何广告。我在连接过程中会打开扫描,但一旦连接,我就会重新打开它。否则,您将无法支持多个同时连接。
【解决方案3】:

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

我的测试手机用了 4 年,所以有时需要超过 20 秒才能返回 onConnectionStateChange....

【讨论】:

    【解决方案4】:

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

    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()
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-14
      • 2018-10-12
      • 2016-10-09
      • 2014-05-05
      • 2013-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      相关资源
      最近更新 更多