2013-06-19 2 views
0

У меня возникла неудобная проблема (может быть, для меня). Я использую таймер для выполнения программирования Tcp listner и сокетов. Я открываю сокет для прослушивания любых данных, присутствующих на порту, отправленном с другого устройства Android (правильно работающего). Я создал 2 приложения для тестирования приема данных, один из них просто фиктивный, а второй - мое основное приложение. Я получаю исключение в своем основном приложении, но не в фиктивном приложении.Network on MainThread Exception (одно приложение работает, другое исключение для исключения)

Исключение: android.os.NetworkonMainThreadException

код точно так же в обоих приложениях здесь это

onCreate() содержит

timer2 = new Timer(); 
     timer2.schedule(new TimerTask() {   
      @Override 
      public void run() { 
       TimerMethod(); 
      } 

     }, 0, 1000); 

TimerMethod() выглядит следующим образом

private void TimerMethod() 
    { 
     this.runOnUiThread(Timer_Tick); 
    } 

Timer_Tick является:

private Runnable Timer_Tick = new Runnable() { 
     public void run() { 
      try 
      { 
       runTcpServer(); 
      } 

      catch(Exception a) 
      { 
       TextView tv = (TextView) findViewById(R.id.textView1); 
       tv.setText(a.toString()); 
      } 

     } 
    }; 

И главный метод Tcp слушать данные на порт

public void runTcpServer() 
    { 
     ServerSocket ss = null; 
     try { 
      ss = new ServerSocket(TCP_SERVER_PORT); 
      //ss.setSoTimeout(10000); 
      //accept connections 
      Socket s = ss.accept(); 
      BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); 
      BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 
      //receive a message 
      String incomingMsg = in.readLine() + System.getProperty("line.separator"); 

      TextView tv= (TextView) findViewById(R.id.textView2); 
      //Log.d("TcpServer", "received: " + incomingMsg); 
      tv.append(incomingMsg); 
      //send a message 
      String outgoingMsg = "goodbye from port " + TCP_SERVER_PORT + System.getProperty("line.separator"); 
      out.write(outgoingMsg); 
      out.flush(); 
      Log.d("TcpServer", "sent: " + outgoingMsg); 
      //textDisplay.append("sent: " + outgoingMsg); 

      //SystemClock.sleep(5000); 
      s.close(); 
     } catch (InterruptedIOException e) { 
      //if timeout occurs 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     finally { 
      if (ss != null) { 
       try { 
        ss.close(); 
       } catch (IOException e) { 
        Log.d("Error",e.toString()); 
       } 
      } 
     } 
    } 

Исключение я получаю, когда я звоню runTcpServer() в Timer_Tick

ответ

1

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

http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

Проверить выше ссылку

Я предлагаю вам использовать AsyncTask.

http://developer.android.com/reference/android/os/AsyncTask.html

Используйте AsyncTask и переместить runTcpServer(). Также помните, что вы не можете обновлять ui из фонового потока. Вам нужно будет использовать runOnUiThread или обновить ui в onPostExecute

Переведите всю свою связанную с сетью операцию на doInbackground(). Переместите снизу на onPostExecute(). Вы можете вернуть результат вычисления в doInbackground(). На основании результатов щ обновления в onPostExecute

TextView tv= (TextView) findViewById(R.id.textView2); 
     //Log.d("TcpServer", "received: " + incomingMsg); 
    tv.append(incomingMsg); 
+0

Почему он запущен в фиктивном приложении, созданном для тестирования? полученные данные верны. –

+0

Что вы подразумеваете под созданием фиктивного приложения? – Raghunandan

+0

Тестируемое приложение с такой же процедурой, как указано выше, работает правильно. –

2

Это ошибка

this.runOnUiThread(Timer_Tick); 

Никогда не запускайте сетевую задачу в пользовательском интерфейсе нить (основной поток)!

Или использовать эту функцию, чтобы включить сетевую задачу в UI потоке, но это не справедливо

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 

StrictMode.setThreadPolicy(policy); 
+0

Почему это работает в фиктивном приложении, созданное только для тестирования? –

+0

Операции с сетью могут включать непредсказуемые задержки. Чтобы это не вызвало плохой пользовательский интерфейс, всегда выполняйте сетевые операции в отдельном потоке из пользовательского интерфейса. Класс AsyncTask предоставляет один из самых простых способов запуска новой задачи из потока пользовательского интерфейса. –

+0

, чтобы включить сетевую задачу в потоке пользовательского интерфейса. См. Edit –

1

ошибка видна вы выполняете таймер на UI тему this.runOnUiThread(Timer_Tick);, работа сети должна всегда выполняться на рабочем потоке, а не просто делать новый Thread(new Timer_Tick()).start();, выполняя работу сети (как они это длительный процесс), поэтому пользовательский интерфейс не реагирует на завершение работы сети.

Добавление Я видел это андроид вопрос, Вы можете использовать AsyncTask См http://developer.android.com/reference/android/os/AsyncTask.html После ОС Android 2.3 Сеть операции на UI потоке не допускается