2012-06-05 56 views
0

我開發一個UDP聊天應用程序在後臺線程。所有網絡處理都在服務內部的線程中。我仍然收到3.1和4.0操作系統的錯誤信息。對於2.3及以下版本,它工作正常。問題:我應該創建兩個應用程序,一個用於版本2.3及以下,另一個用於版本3.0及更高版本?根據LogCat調用寫入(byte [] out)方法時發生錯誤。NetworkOnMainThreadException即使裏面有服務

如果我禁用StrictMode的集成電路芯片的應用程序工作正常。

public class ChatService extends Service { 
    private Binder binder; 
    private ComThread comThread; 

    public IBinder onBind(Intent intent) { 
     return binder; 
    } 

    public void onCreate() { 
    } 

    public int onStartCommand(Intent intent, int flags, int startId) { 
     binder = new ChatServiceBinder(); 
     start(); 
     return super.onStartCommand(intent, flags, startId); 
    } 

    public synchronized void start() { 
     comThread = new ComThread(); 
     comThread.start(); 
    } 

    public void onDestroy() { 
     stop(); 
    } 

    public void write(byte[] out) { 
     comThread.write(out); 
    } 

    public synchronized void stop() { 
     if (comThread != null) { 
      comThread.cancel(); 
      comThread = null; 
     } 
    } 

    private class ComThread extends Thread { 
     private static final int BCAST_PORT = 2562; 
    DatagramSocket mSocket; 
    InetAddress myBcastIP, myLocalIP; 

    public ComThread() { 

     try { 
      myBcastIP = getBroadcastAddress(); 
      if (D) 
       Log.d(TAG, "my bcast ip : " + myBcastIP); 

      myLocalIP = getLocalAddress(); 
      if (D) 
       Log.d(TAG, "my local ip : " + myLocalIP); 

      mSocket = new DatagramSocket(BCAST_PORT); 
      mSocket.setBroadcast(true); 

     } catch (IOException e) { 
      Log.e(TAG, "Could not make socket", e); 
     } 
    } 

    public void run() { 

     try { 

      byte[] buf = new byte[1024]; 
      if (D) 
       Log.d(TAG, "run(), com thread startet"); 
      // Listen on socket to receive messages 
      while (true) { 
       DatagramPacket packet = new DatagramPacket(buf, buf.length); 
       mSocket.receive(packet); 

       InetAddress remoteIP = packet.getAddress(); 
       if (remoteIP.equals(myLocalIP)) 
        continue; 

       String s = new String(packet.getData(), 0, 
         packet.getLength()); 
       if (D) 
        Log.d(TAG, "run(), " + s); 

       Message msg = new Message(); 
       msg.obj = s; 
       msg.arg1 = MessageHandler.MSG_IN; 
       state.getHandler().sendMessage(msg); 

      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Write broadcast packet. 
    */ 
    public void write(byte[] buffer) { 
     try { 
      String data = new String(buffer); 
      DatagramPacket packet = new DatagramPacket(data.getBytes(), 
        data.length(), myBcastIP, BCAST_PORT); 
      mSocket.send(packet); 
     } catch (Exception e) { 
      Log.e(TAG, "write(), Exception during write", e); 
     } 
    } 

    /** 
    * Calculate the broadcast IP we need to send the packet along. 
    */ 
    private InetAddress getBroadcastAddress() throws IOException { 
     WifiManager mWifi = (WifiManager) state 
       .getSystemService(Context.WIFI_SERVICE); 

     WifiInfo info = mWifi.getConnectionInfo(); 
     if (D) 
      Log.d(TAG, "\nWiFi Status: " + info.toString()); 

     // DhcpInfo is a simple object for retrieving the results of a DHCP 
     // request 
     DhcpInfo dhcp = mWifi.getDhcpInfo(); 
     if (dhcp == null) { 
      Log.d(TAG, "Could not get dhcp info"); 
      return null; 
     } 

     int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask; 
     byte[] quads = new byte[4]; 
     for (int k = 0; k < 4; k++) 
      quads[k] = (byte) ((broadcast >> k * 8) & 0xFF); 

     // Returns the InetAddress corresponding to the array of bytes. 
     return InetAddress.getByAddress(quads); // The high order byte is 
               // quads[0]. 
    } 

    private InetAddress getLocalAddress() throws IOException { 

     try { 
      for (Enumeration<NetworkInterface> en = NetworkInterface 
        .getNetworkInterfaces(); en.hasMoreElements();) { 
       NetworkInterface intf = en.nextElement(); 
       for (Enumeration<InetAddress> enumIpAddr = intf 
         .getInetAddresses(); enumIpAddr.hasMoreElements();) { 
        InetAddress inetAddress = enumIpAddr.nextElement(); 
        if (!inetAddress.isLoopbackAddress()) { 
         return inetAddress; 
        } 
       } 
      } 
     } catch (SocketException ex) { 
      Log.e(TAG, ex.toString()); 
     } 
     return null; 
    } 

    public void cancel() { 
     try { 
      mSocket.close(); 
     } catch (Exception e) { 
      Log.e(TAG, "close() of connect socket failed", e); 
     } 
    } 
} 

public class ChatServiceBinder extends Binder { 
    private ChatService service = ChatService.this; 

    public ChatService getService() { 
     return service; 
    } 
}   

}

}

感謝。所允許的,除非它的服務(而不是你擁有了它的子類)內

+1

如果您收到該消息的話,好像你沒有正確地實現線程。發佈您的代碼。 – Squonk

+1

你不應該創建兩個應用程序。請。 –

+0

我目前的應用程序工作正常,操作系統版本2.3和更低。爲了使它在ICS下工作,我必須禁用StrictMode。 2.3操作系統無法識別StrictMode,我必須轉到項目屬性並將項目構建目標更改爲Android 4.0。所以我創建了一個構建目標爲2.3的應用程序,另一個構建目標爲4.0並禁用了StrictMode。什麼是對這個問題的正確解決方案?謝謝。 – SeanZhang2012

回答

0

晚了一點,而不是一個超級巨大的答案,但在Android 3+的Runnable不會被解釋。我知道它是一種限制性檢查,因爲您可以自由創建任何您想要的任何內容,但是UDP多播並非所有Android開發人員都會遇到的問題。希望這可以幫助。

+0

這個問題可能比簡單得多 - 因爲溼眶客在評論排序指出,從UI線程調用comThread.write()不會導致操作在後臺線程正在做的,而它導致網絡操作發生在調用該方法的主UI線程上。解決方法是將消息傳遞給線程,或爲此特定目的啓動它,並從其run方法調用 - 僅調用Thread對象的任意方法不會完成線程。 –

+0

啊!所以現在通過顯示/隱藏鏈接將註釋截斷爲3。我甚至沒有看到最近的3條評論,包括Squonk超出他對丟失代碼的抱怨。 – garlicman

相關問題