Полностью отключите Bluetooth-устройство с низким энергопотреблением

Я подключаюсь к устройству BLE с connectGatt() метод в Android. Это прекрасно работает.

Когда я отключаюсь, я использую следующее:

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(), Само устройство, кажется, думает, что оно все еще подключено, так как я не могу перевести его в режим трансляции видимости (что происходит, если у него уже есть соединение). Однако, если я убью приложение и открою его снова, я смогу перевести устройство в режим вещания. Это говорит о том, что приложение не было правильно отключено.

Есть идеи, что я здесь пропустил?

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()) {
        device = bluetoothAdapter.getRemoteDevice(macAddress);

        if (device == null) {
            this.sendToast("Device Not Available");
        } else {
            Log.d("BLED", "Connecting...");
            gatt = device.connectGatt(this, true, gattCallback);
        }
    }
}

Это абсолютно логично, потому что вы не отключаетесь перед закрытием Гатт.

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

попробуйте вызвать этот метод перед закрытием GATT

Как указывалось ранее, проблема вызвана многократным вызовом 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()
        }
    }
}

У меня возникла та же проблема, и я обнаружил две возможные причины: 1. Был такой же, как ответ @nilsi, подключайтесь к одному и тому же устройству более одного раза за одно сканирование. → решено блокировкой и списком 2. подключиться к устройству за одно сканирование и не получить onConnectionStateChange, чем я снова сканировал, это привело ко второму подключению к тому же устройству. → решается путем сохранения объекта BluetoothGatt при вызове device.connectGatt () и вызове object.disconnect(), object.close () перед сканированием.

Моему тестовому телефону 4 года, поэтому иногда требуется более 20 секунд, чтобы вернуть OnConnectionStateChange....

Другие вопросы по тегам