Как сделать процесс подключения Bluetooth SPP более надежным?
Мы собираемся выпустить новую версию нашего программного обеспечения, и для последующей версии наша цель - сделать процесс подключения для наших соединений Bluetooth SPP более надежным. Мы используем модуль RN42 в наших продуктах, и в настоящее время иногда может потребоваться более одной попытки подключения к нашим платам.
Вот мой текущий код:
class ConnectThread extends Thread {
BluetoothDevice mDevice;
public ConnectThread(BluetoothDevice device) throws SecurityException, NoSuchMethodException {
mDevice = device;
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
btSocket = mDevice.createInsecureRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
Log.e("Error", "Could not create socket!");
}
}
public void cancel() {
interrupt();
try {
Log.i("Treadmill", "in connect thread cancellation");
btSocket.close();
} catch (IOException localIOException) {
Log.e("Treadmill", "exception + " + localIOException.getMessage());
}
}
public void run() {
btAdapter.cancelDiscovery();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e("whatever", "InterruptedException: " + e.getMessage(), e);
}
try {
btSocket.connect();
Log.i("Treadmill", "After Connect");
} catch (IOException ioe) {
Log.i("Treadmill", "Trying Fallback");
try {
Method m;
try {
btSocket.close();
m = mDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[]{int.class});
btSocket = (BluetoothSocket) m.invoke(mDevice, 1);
Thread.sleep(500);
btSocket.connect();
} catch (IllegalArgumentException e) {
Log.e("whatever", "IllegalArgumentException: " + e.getMessage(), e);
} catch (IllegalAccessException e) {
Log.e("whatever", "IllegalAccessException: " + e.getMessage(), e);
} catch (InvocationTargetException e) {
Log.e("whatever", "InvocationTargetException: " + e.getMessage(), e);
} catch (NoSuchMethodException e) {
Log.e("whatever", "NoSuchMethodException: " + e.getMessage(), e);
} catch (InterruptedException e) {
Log.e("whatever", "InterruptedException: " + e.getMessage(), e);
}
} catch (IOException ioe2) {
Log.e("Treadmill", "Failed to connect to Bluetooth device: " + ioe2.getMessage());
eventHandler.obtainMessage(MESSAGE_ERRORCONNECT, 0, 0, getResources().getString(R.string.connerr) + ": " + ioe2.getMessage()).sendToTarget();
try {
btSocket.close();
} catch (IOException localIOException2) {
Log.e("Error", "IO Exception!");
}
return;
}
}
eventHandler.obtainMessage(MESSAGE_CONNECT, 0, 0, "").sendToTarget();
synchronized (this) {
connectThread = null;
}
manageConnectedSocket(btSocket);
}
}
Даже с отступлением к отражению соединение периодически прерывается на некоторых устройствах. Я получаю следующую ошибку:
find_rfc_slot_by_id unable to find RFCOMM slot id: XX
(XX
число, которое увеличивается при каждой попытке соединения).
затем следует:Failed to connect to Bluetooth device: read failed, socket might closed or timeout, read ret: -1
Кто-нибудь знает, как избежать этих ошибок.
Интересно, для сравнения. Я тестирую на двух планшетах. Один планшет Samsung Galaxy Tab 4, кажется, работает очень хорошо, а другой, Astro Tab A10, кажется немного более прерывистым, если вы не подождете несколько секунд между подключением и отключением.
1 ответ
Для более надежного соединения означает, что даже приложение было закрыто, Bluetooth должен оставаться подключенным в фоновом режиме. Ниже приведено рабочее решение, которому я следовал в своем приложении, чтобы поддерживать связь Bluetooth. Сначала создайте класс, который расширяет службу, потому что служба работает в фоновом режиме, даже если приложение закрыто, пока вы не вызовете методы stopService или stopSelf.
при запуске класса BluetoothService передайте Bluetooth-адрес Mac для подключения и запуска в фоновом режиме. Образец кода:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null){
String deviceg = intent.getStringExtra("bluetooth_device");
if (deviceg != null){
connectToDevice(deviceg);
}
}
return START_STICKY;
}
Ниже приведен метод подключения к устройству, который идентифицирует MAC-адрес в устройстве Bluetooth.
public synchronized void connectToDevice(String macAddress){
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
if (mConnectedThread != null){
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectThread = new ConnectBtThread(device);
toast("connecting");
mConnectThread.start();
}
Это мой класс Thread внутри BluetoothService, который работает в отдельном коде потока:
private class ConnectBtThread extends Thread{
private final BluetoothSocket mSocket;
private final BluetoothDevice mDevice;
public ConnectBtThread(BluetoothDevice device){
mDevice = device;
BluetoothSocket socket = null;
try {
socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(B_UUID));
} catch (IOException e) {
e.printStackTrace();
}
mSocket = socket;
}
@Override
public void run() {
if (mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
try {
mSocket.connect();
Log.d("service","Bluetooth one running (connected)");
} catch (IOException e) {
try {
mSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
connected(mSocket);
}
public void cancel(){
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Это прекрасно работает для нашего приложения. Если вы хотите получить доступ к методам обслуживания, привяжите этот сервис к своей деятельности.