2012-06-11 148 views
2

我正在開發一個Android應用程序。與主線程溝通工作線程

此應用程序將有一個服務器來啓動DatagramSocket作爲服務器。它會等待傳入的消息。當套接字收到消息時,我會處理它。

要啓動UDP服務器套接字,我要使用本地服務。此服務將有一個工作線程,我將在其中收聽傳入的消息。

這是我未完成本地服務實現:

public class UDPSocketBackgroundService extends Service 
{ 
    private static final String TAG = "UDPSocketBackgroundService"; 
    private ThreadGroup myThreads = new ThreadGroup("UDPSocketServiceWorker"); 
    private Handler mServiceHandler; 

    @Override 
    public void onCreate() 
    { 
     super.onCreate(); 
     Log.v(TAG, "in onCreate()"); 
    } 

    @Override 
    public IBinder onBind(Intent arg0) 
    { 
     try 
     { 
      new Thread(myThreads, new UDPServerThread("X", 8888)).start(); 
     } 
     catch (IOException e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

這是我也未完成輔助線程執行:

public class UDPServerThread extends Thread 
{ 
    private static final int MESSAGE_SIZE = 256; 

    protected DatagramSocket socket = null; 
    protected boolean end = false; 

    public UDPServerThread(String serverName, int port) throws IOException 
    { 
     super(serverName); 
     socket = new DatagramSocket(port); 
    } 

    public void run() 
    { 
     while (!end) 
     { 
      try 
      { 
       byte[] buf = new byte[MESSAGE_SIZE]; 

       // Wait an incoming message. 
       DatagramPacket packet = new DatagramPacket(buf, buf.length); 
       socket.receive(packet); 
       // TODO: Notify Service with packet received 
      } 
      catch (IOException e) 
      { 
       // TODO Mensaje de error. 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

這些類都有自己的文件(他們是在不同的文件)。

這裏:

socket.receive(packet); 
//TODO: Notify Service with packet received 

我怎麼能通知我們已經收到一個數據包服務?我想發送服務該數據包也。

Here有一個關於如何從主線程到工作線程通信的例子。但是,我不需要,我正在尋找一個關於如何從工作線程到服務進行通信的例子。

我找到了這個example,但我不太瞭解它,因爲在這個例子中,兩個類都聲明它在同一個文件上。如你所見,我是Android開發的新手。

如果你知道更好的方法,請告訴我。

+0

這個代碼有兩個大問題:首先,構造函數Thread(ThreadGroup ,Runnable)'被使用,並且'Thread'作爲第二個參數被傳遞。這是一個錯誤,這個線程永遠不會開始。應該在那裏使用非線程'Runnable'。其次,使用'ThreadGroup'沒有意義。引用*有效的Java *:「*線程組已過時*」。 – Lii

回答

0

當您創建UDPServerThread時,您可以傳入對UDPSocketBackgroundService的引用,然後在接收到數據包時調用其上的一個方法(例如processPacket())。這個processPacket()方法將需要使用某種同步。

這裏的相關功能摘錄的代碼:即去這種方法,UDPSocketBackgroundService現在是「緊耦合」與UDPServerThread

public class UDPSocketBackgroundService extends Service 
{ 
    .... 
    @Override 
    public IBinder onBind(Intent arg0) 
    { 
     try 
     { 
      new Thread(myThreads, new UDPServerThread(this, "X", 8888)).start(); 
      // Notice we're passing in a ref to this ^^^ 
     } 
     ... 
    } 
    public void processPacket(DatagramPacket packet) 
    { 
     // Do what you need to do here, with proper synchronization 
    } 
} 

public class UDPServerThread extends Thread 
{ 
    private static final int MESSAGE_SIZE = 256; 

    protected DatagramSocket socket = null; 
    protected boolean end = false; 
    protected UDPSocketBackgroundService = null; 

    public UDPServerThread(UDPSocketBackgroundService service, String serverName, int port) throws IOException 
    { 
     super(serverName); 
     this.service = service; 
     socket = new DatagramSocket(port); 
    } 

    ... 

    public void run() 
    { 
     while (!end) 
     { 
      try 
      { 
       byte[] buf = new byte[MESSAGE_SIZE]; 

       // Wait an incoming message. 
       DatagramPacket packet = new DatagramPacket(buf, buf.length); 
       socket.receive(packet); 
       service.processPacket(packet); 
      } 
      ... 
     } 
     ... 
    } 
} 

通知。一旦你得到這個工作,你可以考慮用更優雅的設計來重構它,在那裏耦合少,但現在這應該讓你去:)

+0

感謝您的回答,但我還有一個問題:我的服務位於UDPServerThread的另一個線程中。如果我從UDPServerThread調用服務方法,是否合法? – VansFannel

+0

@ VansFannel,它應該沒問題,但是您必須使用答案中提到的同步,以便解決方案是線程安全的並且一致。一種常見的方法是接收數據的線程將數據排入某種共享隊列,在這種情況下是服務隊列,允許它們繼續接收數據。 – Brady

+0

@VansFannel,這是如何解決你的? – Brady