2014-01-27 3 views
2

Я разработал приложение Bluetooth, которое общается с устройством последовательного порта, и пока связь (начало соединения, обмен данными и завершение потока) отлично работает.Приложение BluetoothChat падает на onDestroy() в Android 4.4

Тем не менее, у меня возникла странная проблема с соединением Bluetooth при тестировании на Nexus 4 (Android 4.4.2). Когда я выхожу из приложения с помощью кнопки «Назад», onDestroy() запускается как обычно, но приложение выходит из строя с сообщением об ошибке «К сожалению, остановилось».

Я проверил журнал и нет точки крушения. следующее сообщение об ошибке показано

"01-29 16: 57: 11,372: А/Libc (8684): фатальный сигнал 11 (SIGSEGV) при 0x00000008 (код = 1), поток 8775 (резьба-327)"

`, за которым следует очень длинная трассировка стека отладки.

Я попытался использовать образец приложения Bluetooth с веб-сайта разработчика Android, чтобы проверить, является ли это моей собственной проблемой реализации, и возникает такая же проблема.

<!---- code --> 
@Override 
public void onDestroy() { 
super.onDestroy(); 
// Stop the Bluetooth chat services 
if (mChatService != null) mChatService.stop(); 
if(D) Log.e(TAG, "--- ON DESTROY ---"); 
} 

В BluetoothChatService.java это код для stop().

/** 
* Stop all threads 
*/ 
public synchronized void stop() { 
    if (D) Log.d(TAG, "stop"); 

    if (mConnectThread != null) { 
     mConnectThread.cancel(); 
     mConnectThread = null; 
    } 

    if (mConnectedThread != null) { 
     mConnectedThread.cancel(); 
     mConnectedThread = null; 
    } 

    if (mSecureAcceptThread != null) { 
     mSecureAcceptThread.cancel(); 
     mSecureAcceptThread = null; 
    } 

    if (mInsecureAcceptThread != null) { 
     mInsecureAcceptThread.cancel(); 
     mInsecureAcceptThread = null; 
    } 
    setState(STATE_NONE); 
} 

Это не происходит для Android 4.2.1 (Galaxy Nexus) и Android 4.3 (Samsung S4).

Любая идея, как исправить это? Если это ошибка Android, есть ли у нее обходной путь?

Большое спасибо заранее.

ответ

1

Проблема заключается в том, что ваше приложение пытается получить доступ к сокету после close(). В частности, вызов available() на разъеме inputstream после закрытия разъема вызывает segfault. Это помогло мне убедиться, что нить ничего не читает из потока сокета. После этого вы можете позвонить mmSocket.close(). В основном, прервите свой поток перед его закрытием и попросите поток прослушать прерывание.

изменить метод stop() к следующему:

public synchronized void stop() { 
    if (D) Log.d(TAG, "stop"); 

    /* if (mConnectedThread.mmSocket.isConnected()){ 
     mConnectedThread.interrupt(); 
     mConnectThread.cancel(); 

    }*/ 

    if (mConnectThread != null) { 
     mConnectThread.cancel(); 
     mConnectThread = null; 
    } 

    if (mConnectedThread != null) { 
     mConnectedThread.interrupt(); 
     mConnectedThread.cancel(); 
     mConnectedThread = null; 
    } 

    if (mSecureAcceptThread != null) { 
     mSecureAcceptThread.cancel(); 
     mSecureAcceptThread = null; 
    } 

    setState(STATE_NONE); 
} 

и к вашему методу ConnectedThread run() добавить следующий фрагмент кода:

public void run() { 
    ... 
    while (condition) { 
     if (isInterrupted()) 
      return; 
     ... 
    } 
    ... 
} 

Надеется, что это помогает! :)

+0

Спасибо, это сработало для меня! – Lorteld

+0

Рад помочь :) – Ahassanein

0

Источник этой аварии является нулевым указателем на исключение

private final void setStatus(int resId) { 
    final ActionBar actionBar = getActionBar(); 
    actionBar.setSubtitle(resId); 
} 

, но это происходит только тогда, когда OnDestroy() обратный вызов обслуживается. (BTW этот обратный вызов происходит из-за кнопки возврата, т.е. onPause(), за которой следует onStop(), за которым следует onDestroy().

Я нашел 2 способа справиться с этой ситуацией 1) В BluetoothChat.java замените код

private final Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case MESSAGE_STATE_CHANGE: 
      if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); 
      switch (msg.arg1) { 
      case BluetoothChatService.STATE_CONNECTED: 
       setStatus(getString(R.string.title_connected_to, mConnectedDeviceName)); 
       mConversationArrayAdapter.clear(); 
       break; 
      case BluetoothChatService.STATE_CONNECTING: 
       setStatus(R.string.title_connecting); 
       break; 
      case BluetoothChatService.STATE_LISTEN: 
      case BluetoothChatService.STATE_NONE: 
       setStatus(R.string.title_not_connected); 
       break; 
      } 
      break; 

от

private final Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case MESSAGE_STATE_CHANGE: 
      if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); 
      switch (msg.arg1) { 
      case BluetoothChatService.STATE_CONNECTED: 
       setStatus(getString(R.string.title_connected_to, mConnectedDeviceName)); 
       mConversationArrayAdapter.clear(); 
       break; 
      case BluetoothChatService.STATE_CONNECTING: 
       setStatus(R.string.title_connecting); 
       break; 
      case BluetoothChatService.STATE_LISTEN: 
       setStatus(R.string.title_not_connected); 
       break; 
      case BluetoothChatService.STATE_NONE: 
       //setStatus(R.string.title_not_connected); 
       break; 
      } 
      break; 

2) другой способ заключается в сдвиге Кодекса

// Stop the Bluetooth chat services 
if (mChatService != null) mChatService.stop(); 

из onDestroy() to onPause() функция обратного вызова.

Я запускаю свое приложение на Android 4.2.2, поэтому не уверен, что вышеприведенное решение применимо для Android 4.4.

Приложение также вылетает после изменения ориентации экрана. Чтобы преодолеть это, я принял ориентацию портрета для своего приложения через файл манифеста Android. Но лучше использовать решение onSaveInstanceState (bundle).

+0

Вариант 2 для меня невозможен, так как моему приложению необходимо поддерживать живое соединение Bluetooth, даже когда создаются новые действия (например, диалоговые окна обработки и т. Д.). Я пробовал вариант 1, и он не работает для меня. Использование Android 4.4.2. – Lorteld

0

также взглянуть на решение, предложенное на аналогичный вопрос о BlueToothChat кода на BluetoothChat example: NullPointerException

+0

Не помогает. Помните, что это ошибка сегментации (сигнал 11), а не исключение нулевого указателя в Java. – Lorteld

3

Попробуйте это: в классе mConnectedThread, сделать флаг как

private boolean stopThread = false; 

, а затем в перспективе () метод изменения цикла:

while (true) {... 

в

while (!stopThread) {... 

, а затем добавить это в метод отмены():

stopThread = true; 
try { 
    mmSocket.close(); 
} catch ... 

Это должно заботиться о вашей проблеме, не знаю, почему они пошли с бесконечным циклом, в первую очередь, из-за отмены метод будет называться, когда его нужно называть ...

Надеюсь, что это поможет :).

Смежные вопросы