Как видно из названия, я пытаюсь найти самый быстрый способ подключения к устройству Bluetooth LE без каких-либо проблем. До сих пор у меня работало создание нового потока и подключение к устройству, обнаруженному в onLeScan
. Этот метод хорошо работает на моем galaxy S9 и galaxy Tab a, так как каждое соединение работает параллельно с другим, что приводит к нахождению устройства за короткое время. Но я не могу получить такой же результат на моей Motorola G4. Даже если сканируются и подключаются только два устройства, иногда требуется более 15-20 секунд, прежде чем вызывается onConnectionStateChange
. Похоже, что один экземпляр Гатта ожидает завершения другого sh.
Другой метод, который я пробовал, - это последовательное подключение к каждому устройству, и, если UUID службы устройства совпадает, я подключусь к этому. устройство. Проблема в этом ожидании подключения к таймауту (то есть onConnectionStateChange
называется). Обходной путь, который я попытался, состоит в том, чтобы вызвать gatt.close()
через 2 секунды после того, как был вызван connectGatt()
. Это хорошо работает, если устройство, которое принудительно отключено, не является целевым устройством. Однако, если я принудительно отключу, когда целевое устройство подключается, я больше не могу подключиться к нему снова (иногда), так как он не будет отображаться в списке отсканированных устройств.
Ваш ввод приветствуется.
Вот соответствующий код:
Это одновременный метод подключения.
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
if (!deviceList.contains(device) && rssi <= -15 && rssi >= -80) {
if (connectModeAuto && mBluetoothGatt == null) {
Log.d(TAG, "Device name xxx:" + device.getName() + " uuid:" + device.getAddress() + " " + rssi);
connectToDevice(device);
}
}
}
});
t.start();
}
public void connectToDevice(BluetoothDevice device) {
Log.d(TAG,"Connecting to device xxx");
Method connectGattMethod;
mBluetoothGatt = null;
BluetoothGatt gatt;
///*
try {
connectGattMethod = device.getClass().getMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
try {
gatt = (BluetoothGatt) connectGattMethod.invoke(device, this, false, mGattCallback, 2); // (2 == LE, 1 == BR/EDR)
gattList.add(gatt);
} catch (IllegalAccessException e) {
//IllegalAccessException
} catch (IllegalArgumentException e) {
//IllegalArgumentException
} catch (InvocationTargetException e) {
//InvocationTargetException
}
disconnected = false;
gattConnect = false;
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
Это альтернативный способ подключения к устройству
public void connectToDevice(int index,int type) {
BluetoothDevice device = deviceList.get(index);
Method connectGattMethod;
try {
connectGattMethod = device.getClass().getMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
try {
mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, this, autoConnect, mGattCallback, 2); // (2 == LE, 1 == BR/EDR)
//gattList.add(0,gatt);
} catch (IllegalAccessException e) {
//IllegalAccessException
} catch (IllegalArgumentException e) {
//IllegalArgumentException
} catch (InvocationTargetException e) {
//InvocationTargetException
}
disconnected = false;
gattConnect = false;
timeoutThread = null;
timeoutThread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(connectTimeout);
} catch (InterruptedException e) {
Log.d(TAG,"interrupted xxx");
e.printStackTrace();
return;
}
if (!gattConnect) {
Log.d(TAG,"xxx Forcing disconnect");
disconnected = true;
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
mBluetoothGatt = null;
if (deviceList.size() > 0) {
retryConnection();
} else {
scanLeDevice(true);
}
}
}
});
timeoutThread.start();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public void retryConnection() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
deviceList.remove(0);
if (deviceList.size() > 0) {
Log.d(TAG,"Have more devices "+deviceList.size());
connectToDevice(0,1);
}
else {
Log.d(TAG,"search mode");
scanLeDevice(shouldScan);
}
}
});
t.start();
}
public void scanLeDevice(final boolean enable) {
if (enable) {
scanning = true;
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
@Override
public void run() {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
Set<BluetoothDevice> set = new HashSet<>(deviceList);
deviceList.clear();
deviceList.addAll(set);
if (deviceList.size() > 0) {
if (connectModeAuto) {
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
connectToDevice(0,1); // Connect to first device found.
}
});
t2.start();
}
}
}
}, 3000);
boolean scanDidStart = mBluetoothAdapter.startLeScan(mLeScanCallback);
//UUID[] uuids = {SERVICE_UUID};
//mBluetoothAdapter.startLeScan(uuids,mLeScanCallback);
if (scanDidStart) {
Log.d(TAG, "Scan started");
} else {
Log.d(TAG, "Scan did not start");
}
} else {
scanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}