2013-05-11 184 views
2

相似或相同的問題已經回答了here上市網絡設備的

我創建一個Android應用程序,它發送廣播消息到網絡並準備設備回覆我們的列表。

我現在做什麼:

我創建了一個ActivityDeviceManagerWindow.java它調用線程Sender.javaSender.java負責發送廣播消息。

然後,DeviceManagerWindow.java調用另一個線程負責收聽設備響應。一旦設備迴應,回覆中的回覆將被列在活動中。爲此,我有一個名爲deviceListTableLayout

我寫什麼代碼:

DeviceManagerWindow.javaThis method is called when a button for search is pressed

public void searchDevice(View v) throws IOException, InterruptedException 
{ 
    //Log.v("TableLayout:",view.toString()); 
    sendMulticastFlyport = new Thread(new FlyportSender(MAC)); 
    sendMulticastFlyport.start(); 
    new Thread() 
    { 
     public void run() 
     { 
      MulticastSocket socketComputer=null; 
      try 
      { 
       socketComputer = new MulticastSocket(WifiConstants.COMPUTER_RECV_PORT); 
       socketComputer.joinGroup(InetAddress.getByName(WifiConstants.COMPUTER_NETWORK_ADDR)); 
       socketComputer.setSoTimeout(1*60*1000); 
       byte[] inBufComputer = new byte[1024]; 
       DatagramPacket inPacketComputer = new DatagramPacket(inBufComputer, inBufComputer.length); 

       while(true) 
       { 
        System.out.println("Listening..."); 
        socketComputer.receive(inPacketComputer); 
        System.out.println("Received"); 
        String msg = new String(inBufComputer, 0, inPacketComputer.getLength()); 
        DeviceInformation device = new DeviceInformation(1, msg, inPacketComputer.getAddress().toString()); 

        addDevice(device, false, 1); 

        Log.v("Received:","Received Computer From :" + inPacketComputer.getAddress() + " Msg : " + msg); 
        //System.out.write(inPacket.getData(),0,inPacket.getLength()); 
        System.out.println(); 
        Thread.sleep(2000); 
       } 
      } 
      catch(Exception e) 
      { 
       Log.v("Exception:","During Receiving Computer: "+e.toString()); 
       try 
       { 
        addDevice(null, true, 1); 
       } 
       catch (IOException e1) 
       { 
        Log.v("Exception:", "Computer End Error: " +e1); 
       } 
      } 
      finally 
      { 
       socketComputer.close(); 
      } 
     } 
    }.start(); 

下面的代碼創建一個列表:

public void addDevice(DeviceInformation device, boolean bool, int type) throws IOException 
{ 
    TableLayout tb = (TableLayout) findViewById(R.id.DeviceList); 
    Log.v("addDevice","Called"); 
    if(bool) 
    { 
     LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 
     TableRow tr = new TableRow(getApplicationContext()); 
     TextView tv = new TextView(getApplicationContext()); 
     System.out.println(tb); 
     tv.setLayoutParams(layout); 
     tr.setLayoutParams(layout); 
     String message; 
     Log.v("addDevice","Device Timeout"); 
     switch(type) 
     { 
      case 1: 
       computerEnd=true; 
       break; 
      case 2: 
       raspberryEnd=true; 
       break; 
      case 3: 
       flyportEnd=true; 
       break; 
     } 
     if(computerEnd && raspberryEnd && flyportEnd) 
     { 
      if(rowCounter>0) 
      { 
       message = "No More Devices"; 
      } 
      else 
      { 
       message = "No Devices Found"; 
      } 
      tv.setText(message); 
      tv.setTextColor(Color.WHITE); 
      if(rowCounter%2==0) 
      { 
       tr.setBackgroundColor(Color.DKGRAY); 
      } 
      else 
      { 
       tr.setBackgroundColor(Color.GRAY); 
      } 
      tv.setVisibility(1); 
      tr.addView(tv); 
      tb.addView(tr); 
     } 
    } 
    else 
    { 
     LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 
     TableRow tr = new TableRow(getApplicationContext()); 
     TextView tv = new TextView(getApplicationContext()); 

     tv.setLayoutParams(layout); 
     tr.setLayoutParams(layout); 

     Log.v("addDevice","Received"); 
     String textToDisplay = device.getDeviceTypeString()+"\n"+device.getIPAddress(); //Write the text to display 
     tv.setText(textToDisplay); 
     tv.setTextColor(Color.WHITE); 
     Drawable img; 
     if(device.getDeviceType()==1) 
     { 
      img = getApplicationContext().getResources().getDrawable(R.drawable.pc); 
     } 
     else if(device.getDeviceType()==2) 
     { 
      img = getApplicationContext().getResources().getDrawable(R.drawable.raspberry); 
     } 
     else 
     { 
      img = getApplicationContext().getResources().getDrawable(R.drawable.flyport); 
     } 
     img.setBounds(0,0,70,45); 
     tv.setCompoundDrawables(null, null, img, null); 
     tv.setOnClickListener(new OnClickListener() 
     { 
      @Override 
      public void onClick(View v) 
      { 

      } 
     }); 
     if(rowCounter%2==0) 
     { 
      tr.setBackgroundColor(Color.DKGRAY); 
     } 
     else 
     { 
      tr.setBackgroundColor(Color.GRAY); 
     } 
     rowCounter++; 
     Log.v("Result","Device Added"); 
    } 
} 

現在,它顯示了我一個錯誤在logCat中爲:

05-11 22:01:10.165: E/AndroidRuntime(13873): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

我從中得出的結論是隻有UIThread被允許訪問創建的視圖。

以前我曾嘗試:

new Thread() 
{ 
    public void run() 
    { 
     runOnUiThread(){ 
     MulticastSocket socketComputer=null; 
     try 
     { 
      ....   
      .... 
      .... 
    } 
} 

而且那個時候,我收到了一個錯誤:

主線程無法訪問網絡

此之前,我曾試圖用​​方法,其從Receiving.java線程文件中調用。但它也給了一個不創建列表的錯誤。

我嘗試了所有可能的方法。

現在我該怎麼辦?

+0

奇妙的問題...值得一個upvote ..! – 2013-05-11 18:44:47

回答

1

你明白了。現在您可以學習使用Handler將信息傳遞給UI線程(請參閱http://www.techotopia.com/index.php/A_Basic_Overview_of_Android_Threads_and_Thread_handlers)或AsyncTask(請參閱http://developer.android.com/reference/android/os/AsyncTask.html)。

我個人比較喜歡AsyncTask。您可以將執行搜索的代碼粘貼到doInBackground()方法中(不需要使用單獨的線程,doInBackground()已經爲您執行此操作),並將與UI相關的代碼(列表創建代碼)粘貼到onPostExecute( ) 方法。如果AsyncTask沒有足夠清晰地顯示鏈接的工作方式,可以搜索更多的AsyncTask示例。

編輯:如果你打算讓你的設備搜索代碼無限期地運行,那麼你不得不求助於Handler,因爲AsyncTask需要在運行onPostExecute()之前完成doInBackground()方法。查看哪種方案更適合您的需求。

+0

讓我試試....這可能有所幫助。 – 2013-05-11 17:30:54

+0

我想它應該工作..!謝謝..!! – 2013-05-11 18:45:33

+0

我會盡快將它標記爲正確的,我檢查代碼..我想爲AsyncTask提供的鏈接是足夠的..可以U請給我一個很好的教程。 – 2013-05-11 18:46:29