Приложение, использующее профиль bluetooth SPP, не работает после обновления с Android 4.2 до Android 4.3

Я написал простое приложение, основанное на bluetoothChat. Я общаюсь между телефоном и модулем Bluetooth, используя профиль SPP. Телефон всегда инициирует сообщение. Приложение отлично работало на Android 4.2, используя Nexus 3 и Samsung Galaxy 3. После обновления до Android 4.3 приложение больше не работает. Я все время подключаюсь, я могу отправить outpustream и получить нужные данные, но после первой команды выходного streamа приложение всегда отключается после 6 секунд. Как показано в приведенном ниже логарифмическом кадре, похоже, что проблема с таймером во входном streamе.

08-23 14:10:00.726: D/mems(23193): STEVAL-MKI106V1 08-23 14:10:00.804: D/Main Activity(23193): firmware version*setdb106V1 08-23 14:10:00.812: D/Main Activity(23193): sent message*setdb106V1 08-23 14:10:00.812: D/BluetoothMEMSCommunication(23193): dans write3 08-23 14:10:00.812: D/BluetoothMEMSCommunication(23193): envoi stream 08-23 14:10:05.812: W/bt-btif(20368): dm_pm_timer expires 08-23 14:10:05.812: W/bt-btif(20368): dm_pm_timer expires 0 08-23 14:10:05.812: W/bt-btif(20368): proc dm_pm_timer expires 08-23 14:10:11.656: E/bt-btm(20368): btm_sec_disconnected - Clearing Pending flag 08-23 14:10:11.656: W/bt-btif(20368): invalid rfc slot id: 15 08-23 14:10:11.656: I/connection(23193): connectionlost 

Что такое dm_pm_timer? Я пытался подключиться по-другому, с безопасным и небезопасным rfcom. Я знаю, что Bluetooth-чат не оптимизирован для получения буфера, поэтому я изменил его, а не эффект. Я также использовал команду flush для outpustream, но и никакого эффекта.

 package com.meneujj.memsbtbis; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.widget.Toast; public class BluetoothMEMSCommunication { // debugging private static final String TAG = "BluetoothMEMSCommunication"; private static final boolean D = true; // eMotion BT h as this standard UUID private static final UUID STANDARD_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // Member fields private final BluetoothAdapter mAdapter; private final Handler mHandler; private int mState; private int handlerCalling; private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; // Constants they indicate the current connection state public static final int STATE_NONE = 0; public static final int STATE_CONNECTED = 3; // now connected to a remote device // constructor. Prepares a new Bluetooth Connection // context The UI Activity Context // handler an Handler to send messages back to the UI Activity public BluetoothMEMSCommunication(Context context, Handler handler, int i) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; handlerCalling = i; } private synchronized void setState(int state) { mState = state; Log.d(TAG, Integer.toString(mState)); mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); } public synchronized void connect(BluetoothDevice device) { // start the thread to connect with the given device if (mConnectThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } // cancel any thread currently running a connection if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } Log.d(TAG,"routine connect lancee"); mConnectThread = new ConnectThread(device); mConnectThread.start(); } private void ConnectionLost() { // Send a failure message back to the activity Message msg = mHandler.obtainMessage(MainActivityMemsBT.CONNECTION_LOST_MESSAGE); Bundle bundle = new Bundle(); bundle.putString(MainActivityMemsBT.TOAST_CONNECTION_LOST, "Device connection was lost"); msg.setData(bundle); mHandler.sendMessage(msg); Log.i("connection","connectionlost"); setState(STATE_NONE); StopAllThreads(); } public synchronized void StopAllThreads() { if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } setState(STATE_NONE); } public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) { // cancel the thread they completed the connection if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } // Cancel any thread currently running a connection if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } // Start the thread to manage the connection and perform transmission mConnectedThread = new ConnectedThread(socket, socketType); mConnectedThread.start(); // Send the name of the connected device back to the UI activity Message msg = mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_DEVICE_NAME); Bundle bundle = new Bundle(); bundle.putString(MainActivityMemsBT.DEVICE_NAME, device.getName()); msg.setData(bundle); mHandler.sendMessage(msg); setState(STATE_CONNECTED); } public void write(byte[] out) { // create temporary object ConnectedThread r; Log.d(TAG,"dans write" + Integer.toString(mState)); // synchronize a copy of the ConnectedThread synchronized (this) { if (handlerCalling == 2) setState(STATE_CONNECTED); if (mState != STATE_CONNECTED) { Log.d(TAG, "different de STATE_CONNECTED"); Log.i(TAG, Integer.toString(handlerCalling)); return;} r= mConnectedThread; } r.write(out); } 

Любая идея есть обходной путь? Или любая очевидная ошибка в моем коде

благодаря

 // Thread runs while attempting to an an outgoing connection with a device. // it runs straight through; the connection either succeeds or fails. private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; private String mSocketType; public ConnectThread(BluetoothDevice device) { mmDevice = device; BluetoothSocket tmp = null; try { tmp = device.createRfcommSocketToServiceRecord(STANDARD_UUID); //tmp = device.createInsecureRfcommSocketToServiceRecord(STANDARD_UUID); /* try { Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); try { tmp = (BluetoothSocket) m.invoke(device, 1); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } */ } catch (IOException e) { } mmSocket = tmp; } public void run () { setName("ConnectThread" + mSocketType); mAdapter.cancelDiscovery(); try { mmSocket.connect(); } catch (IOException e) { try { mmSocket.close(); } catch (IOException e2) { Log.e(TAG, "unable to close() " + mSocketType + "socket during connection failure", e2); } return; } // reset the CoonectThread because the job is over synchronized (BluetoothMEMSCommunication.this) { mConnectThread = null; } connected(mmSocket, mmDevice, mSocketType); } public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } // close connectThread class } private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket, String socketType) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { ConnectionLost(); } mmInStream = tmpIn; mmOutStream = tmpOut; } // Thread to listen to input sockets public void run() { Log.i(TAG, "Begin mConnectedThread"); byte[] buffer = new byte[1024]; // int bytes; int bytesRead = -1; String message = ""; // keep listening to the InputStream while connected while(true) { try { // read from the input stream // bytesRead = mmInStream.read(buffer); // message = message+ new String(buffer, 0, bytesRead); // byte[] byteString = message.getBytes(); Log.i("info","pret a faire read"); bytesRead = mmInStream.read(buffer, 0, 1024); if (bytesRead != -1 && handlerCalling == 1) { mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_READ, bytesRead, -1, buffer).sendToTarget(); } if (bytesRead !=-1 && handlerCalling == 2) { mHandler.obtainMessage(DemoAccelerometer.MESSAGE_READ, bytesRead, -1, buffer).sendToTarget(); } } catch (IOException e) { ConnectionLost(); break; } } } public void write(byte[] buffer) { try{ mmOutStream.write(buffer); // if (handlerCalling == 1) { // mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_WRITE, -1, -1, buffer).sendToTarget(); Log.d(TAG,"envoi stream"); // mmOutStream.flush(); // } } catch (IOException e) { } } public void cancel() { try{ mmSocket.close(); } catch (IOException e) { } } } } 

Мы можем подтвердить Bluetooth-разъединение через 6 секунд при обращении от нашего приложения Nexus 4 к внешнему Bluetooth-ЭКГ (медицинскому устройству) после обновления с Android 4.2 до 4.3. Это происходит специально во время измерения ЭКГ с большим количеством входящих данных (от ЭКГ до приложения для Android), но нет исходящих данных. «Нормальная» связь Bluetooth с некоторыми входящими и исходящими данными время от времени, похоже, не затрагивается.

Через 6 секунд мы видим те же сообщения журналов adb, о которых сообщает JJM

 dm_pm_timer expires dm_pm_timer expires 0 proc dm_pm_timer expires btm_sec_disconnected - Clearing Pending flag 

Этот таймер истекает на стороне Android, что-то вызывает (закрытие выходного streamа из-за отсутствия исходящих данных?) На внешнюю Bluetooth-ЭКГ, которая, в свою очередь, посылает специальную команду ЭКГ, которую мы получаем по входному streamу, который мы никогда не получаем на Nexus 4 с Android 4.2.

Изменение реализации приложения для Android, чтобы иногда отправлять произвольную команду «keep alive» в ЭКГ, решает проблему. Время истечения таймера больше не отображается в журналах adb, и измерение ЭКГ теперь ведет себя так же, как и в Android 4.2.

Спасибо JJM за подсказки.

Я нашел работу. Он отключается, если в течение нескольких секунд нет streamовой активности. Мне удалось несколько streamов ввода или ввода несколько раз в секунду, и он никогда не отключается.

Я нашел в StackOverflow ответ, который помог мне решить проблему. Я предполагаю, что это связано с тем, что inputStream и outputStream не закрываются должным образом и нулевые, а также сокет bluetooth. После использования этой функции:

  * Reset input and output streams and make sure socket is closed. * This method will be used during shutdown() to ensure that the connection is properly closed during a shutdown. * @return */ private void resetConnection() { setState(STATE_NONE); Log.d(TAG, "reset connection"); if (mmInStream != null) { try { mmInStream.close(); } catch (Exception e) { Log.d(TAG,"exception in closing inputstream - " + e.getMessage()); } mmInStream = null; } if (mmOutStream != null) { try { mmOutStream.close(); } catch (Exception e) { Log.d(TAG,"exception in closing outputstream - " + e.getMessage()); } mmOutStream = null; } if (mmSocket != null) { try { mmSocket.close(); } catch (Exception e) { Log.d(TAG,"exception in closing socket - " + e.getMessage()); } mmSocket = null; } } 

в ConnectedThread и вызвать его при необходимости, я удалил эту проблему. Это также может быть проблемой при чтении из inputStream, может быть, потому, что при попытке прочитать ничего не было.

Я предлагаю вам выполнить логическую функцию readWrite (), которая всякий раз, когда вы пишете outputStream, вы также читаете inputStream и отправляете readBuffer в интерфейс с помощью mHandler. Если оба чтения и записи в порядке, то верните true, если один из них поступил не так, как возвращает false, и используйте resetConection перед закрытием ConnectedThread.

Это работало очень хорошо для меня.

UPDATE: (30-SEPT-2013) Я запускаю свое приложение, и я все еще получаю hci_status = 36 через несколько минут. У меня есть приложение, которое подключается к внешнему устройству Bluetooth. Я отправляю данные и получаю данные прибл. 3 раза / сек. Я использую Thread.sleep (300) между write. В моих тестах я получил эту ошибку через несколько минут до почти 30 минут при запуске приложения.

Любая обратная связь приветствуется!

  • Android Studio - локального пути не существует
  • Android + Pair устройства через программный интерфейс Bluetooth
  • Программно подключаться к сопряженному устройству Bluetooth
  • Давайте будем гением компьютера.