Не удается закрыть входной поток

#android #sockets #tcp #inputstream

#Android #сокеты #tcp #входной поток

Вопрос:

в этом приложении я запускаю удаленную службу, где я запускаю отдельный поток для запуска TCP-соединения… при выходе из приложения я должен закрыть входной поток, для которого я прерываю поток и изменяю логическое значение (stopBroadcastRequested) .. когда это выполняется в блоке потока, я закрываю входной поток, но на самом деле он не закрывается… если я вручную введу instream.close в потоке во время обычного выполнения потока, входной поток закроется, как и ожидалось.. но в if (stopBroadcastRequested) {блок кода} это не работает .. может кто-нибудь сказать мне, в чем ошибка, которую я допустил…

 public class BroadcastService extends Service {

    class Task implements Runnable{
    OutputStream outStream = null;
    InputStream inStream = null;

    @Override
    public void run() {
        while(!stopBroadcastRequested){
            Log.i(TAG, "Thread Task started");          
            try {
                isSocketOpen = broadCastComm.isAliveOrOpenSocket("192.168.43.2", 6000, 17, 0);

                if(isSocketOpen){
                    Log.d("SERVICE CLASS", "STARTED THREAD - Writing in output stream");

                    notificationMngr.cancelAll();
                    isShowingNotification = false;
                    outStream = broadCastComm.getCurrentOutputStream();
                    outStream.write(messageToBeSent);
                    if(Integer.valueOf(messageToBeSent[2]) != (byte)0xA0){
                        Log.e("REVERTING", "REVERTING");
                        messageToBeSent = mFormatter.formBroadCastMessage("GET_PERIPH_DATA");
                    }

                    Log.d("OUTPUT STREAM", "Message sent ->"   ByteArrayToString(messageToBeSent));
                }else{
                    connectivityStatusHandler.sendEmptyMessage(0);
                }

                Thread.sleep(3000L);

                if(isSocketOpen){

                }

            } catch (Throwable t) { 
                Log.e(TAG, "Failed to retrieve data in thread", t);
            }
            Log.d("SERVICE CLASS", "End of THREAD");

        }

        if(stopBroadcastRequested){
            Log.e("SERVICE", "STOPPED THREAD");
            try {
                Log.e("*****THREAD", "CLOSED INPUT STARTED");
                if(inStream != null)
                    inStream.close();

                Log.e("*****THREAD", "CLOSED INPUT CLOSED");
                outStream.flush();
                outStream.close();
                Log.e("*****THREAD", "CLOSED OUTPUT");
            } catch (Exception e) {
                Log.e("THREAD", "FAILED TO CLOSE STREAMS");
            }
        }
    }

    public synchronized void stopThread(){
        stopBroadcastRequested = true;
    }

}


@Override
public void onDestroy() {
    super.onDestroy();
    Log.e(TAG, "Service destroying");
    stopBroadcastRequested = true;
    serviceThread.interrupt();


    cleanNotifications();
    broadCastComm.clearConnections();
    //dbHandler.removeCallbacks(dbUpdater);
    try {
        dbHelper.cleanup();
    } catch (Exception e) {
        Log.e("SERVICE", "Failed to clear DB connections");
    }
}
  

}

   ------LOG
05-30 19:28:03.878: ERROR/BroadcastService(20288): Failed to retrieve data in thread
05-30 19:28:03.878: ERROR/BroadcastService(20288): java.lang.InterruptedException
05-30 19:28:03.878: ERROR/BroadcastService(20288):     at java.lang.VMThread.sleep(Native Method)
05-30 19:28:03.878: ERROR/BroadcastService(20288):     at java.lang.Thread.sleep(Thread.java:1213)
05-30 19:28:03.878: ERROR/BroadcastService(20288):     at java.lang.Thread.sleep(Thread.java:1195)
05-30 19:28:03.878: ERROR/BroadcastService(20288):     at      com.RBEI.TTApp.BroadcastService$Task.run(BroadcastService.java:126)
05-30 19:28:03.878: ERROR/BroadcastService(20288):     at java.lang.Thread.run(Thread.java:1019)
05-30 19:28:03.878: DEBUG/SERVICE CLASS(20288): End of THREAD
05-30 19:28:03.878: ERROR/SERVICE(20288): STOPPED THREAD
05-30 19:28:03.878: ERROR/*****THREAD(20288): CLOSED INPUT STARTED
05-30 19:28:03.882: ERROR/*****THREAD(20288): CLOSED INPUT CLOSED
05-30 19:28:03.882: ERROR/*****THREAD(20288): CLOSED OUTPUT
  

Комментарии:

1. Log.e(«SERVICE», «ОСТАНОВЛЕННЫЙ ПОТОК»); Эта строка действительно выполняется?

2. ДА.. он выполнен….

3. когда я даю либо в пределах этого while (buf.available () > 0){}, либо сразу за пределами этого во время обычного выполнения, он закрывается, как ожидалось, … но не работает в прерывании block…is это какая-то проблема с потоками .. например, общий ресурс или что-то в этомроде…

4. Вы вызываете inStream.close(); довольно много раз. Возможно, первый снимок закрывает его, и вы видите сбой закрытия при последующих закрытиях.

5. хммм … если он закроется один раз, тогда все должно быть в порядке .. потому что на сервере он закроется…

Ответ №1:

Вы можете использовать close () только один раз. Просто добавляйте проверку if (inStream != null { inStream.close(); ) каждый раз.

Комментарии:

1. хммм…. когда я ставлю точку останова и проверяю, что это работает … я не уверен, зачем ему нужна эта задержка, чтобы это сработало…

2. что ж, если вы не найдете решения, я полагаю, что помещение этого кода в AsyncTask будет работать нормально. Я думаю, что в настоящее время это должно вызывать у вас какое-то исключение InterruptedException из-за ожидания потока?

3. нет, вовсе нет. Это своего рода оболочка, используемая для выполнения фоновых операций очень эффективным и удобным для пользователя способом. Существует множество руководств, подобных этому: labs.makemachine.net/2010/05/android-asynctask-example

4. Я также предлагаю вам попробовать удалить метод Thread.sleep и проверить, может ли проблема быть воспроизведена

5. хммм …. почему бы не использовать обработчик? думаю, асинхронную задачу необходимо запустить из потока пользовательского интерфейса .. весь этот код выполняется на удаленном service..is это рекомендуется?

Ответ №2:

Вы получаете исключение (InterruptedException) в строке

 Thread.sleep(3000L);
  

Это происходит еще до того, как вы присвоите значение переменной inStream,
итак

 inStream = broadCastComm.getCurrentInputStream();
  

никогда не выполняется. Вы не можете закрыть сокет, который равен null.

Комментарии:

1. я не использую это сейчас …inStream = broadCastComm.getCurrentInputStream();

Ответ №3:

Извините, ребята, проблема заключалась в том, что я неправильно отключал службу, что вызывало все эти проблемы… не использовался надлежащий контекст для отмены привязки в tabactivity.. пришлось использовать getApplicationContext() вместо этого … 🙂