Полностью отключите 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....