Android ApiDemos示例解析(41):App->Service->Messenger Service

前面LocalService 主要是提供同一Application中組件來使用,如果希望支持不同應用或進程使用Service。可以通過Messenger。使用Messgener可以用來支持進程間通信而無需使用AIDL。

下面步驟說明裡Messenger的使用方法:

在Service中定義一個Handler來處理來自Client的請求。
使用這個Handler創建一個Messenger (含有對Handler的引用).
Messenger創建一個IBinder對象返回給Client( onBind方法)。
Client 使用從Service返回的IBinder重新構造一個Messenger 對象,提供這個Messenger對象可以給Service 發送消息。
Service提供Handler接受來自Client的消息Message. 提供handleMessage來處理消息。
在這種方式下,Service沒有定義可以供Client直接調用的方法。而是通過”Message”來傳遞信息。

本例Messenger Service 涉及到兩個類 MessengerServiceActivities 和 MessengerService.

首先看看Service的定義,在MessengerService定義瞭一個IncomingHandler ,用於處理來自Client的消息。

[java] 
/**
 * Handler of incoming messages from clients.
 */ 
class IncomingHandler extends Handler { 
 @Override 
 public void handleMessage(Message msg) { 
 switch (msg.what) { 
 case MSG_REGISTER_CLIENT: 
 mClients.add(msg.replyTo); 
 break; 
 case MSG_UNREGISTER_CLIENT: 
 mClients.remove(msg.replyTo); 
 break; 
 case MSG_SET_VALUE: 
 mValue = msg.arg1; 
 for (int i=mClients.size()-1; i>=0; i–) { 
 try { 
 mClients.get(i).send(Message.obtain(null, 
 MSG_SET_VALUE, mValue, 0)); 
 } catch (RemoteException e) { 
 // The client is dead.  Remove it from the list;  
 // we are going through the list from back to front  
 // so this is safe to do inside the loop.  
 mClients.remove(i); 
 } 
 } 
 break; 
 default: 
 super.handleMessage(msg); 
 } 
 } 

/**
 * Handler of incoming messages from clients.
 */
class IncomingHandler extends Handler {
 @Override
 public void handleMessage(Message msg) {
 switch (msg.what) {
 case MSG_REGISTER_CLIENT:
 mClients.add(msg.replyTo);
 break;
 case MSG_UNREGISTER_CLIENT:
 mClients.remove(msg.replyTo);
 break;
 case MSG_SET_VALUE:
 mValue = msg.arg1;
 for (int i=mClients.size()-1; i>=0; i–) {
 try {
 mClients.get(i).send(Message.obtain(null,
 MSG_SET_VALUE, mValue, 0));
 } catch (RemoteException e) {
 // The client is dead.  Remove it from the list;
 // we are going through the list from back to front
 // so this is safe to do inside the loop.
 mClients.remove(i);
 }
 }
 break;
 default:
 super.handleMessage(msg);
 }
 }
}
然後使用這個IncomingHandler定義一個Messenger。

[java] 
final Messenger mMessenger = new Messenger(new IncomingHandler()); 
final Messenger mMessenger = new Messenger(new IncomingHandler());
應為這種方法采用的“Bound” Service模式,onBind 需要返回一個IBind對象, 可以通過mMessenger.getBinder()返回與這個Messenger關聯的IBinder對象,Client可以通過這個IBinder對象重新構造一個Messenger對象,從而建立起與Service之間的通信鏈路。

[java] 
@Override 
public IBinder onBind(Intent intent) { 
 return mMessenger.getBinder(); 

@Override
public IBinder onBind(Intent intent) {
 return mMessenger.getBinder();
}
再看看Client 的代碼MessengerServiceActivities 在 ServiceConnection的 onServiceConnected的定義,這個方法返回MessengerService 的onBind 定義的IBinder對象:

[java]
/** Messenger for communicating with service. */ 
 Messenger mService = null; 
  
…. 
public void onServiceConnected(ComponentName className, 
 IBinder service) { 
 // This is called when the connection with the service has been  
 // established, giving us the service object we can use to  
 // interact with the service.  We are communicating with our  
 // service through an IDL interface, so get a client-side  
 // representation of that from the raw service object.  
 mService = new Messenger(service); 
 mCallbackText.setText("Attached."); 
  
 // We want to monitor the service for as long as we are  
 // connected to it.  
 try { 
 Message msg = Message.obtain(null, 
 MessengerService.MSG_REGISTER_CLIENT); 
 msg.replyTo = mMessenger; 
 mService.send(msg); 
  
 // Give it some value as an example.  
 msg = Message.obtain(null, 
 MessengerService.MSG_SET_VALUE, this.hashCode(), 0); 
 mService.send(msg); 
 } catch (RemoteException e) { 
 // In this case the service has crashed before we could even  
 // do anything with it; we can count on soon being  
 // disconnected (and then reconnected if it can be restarted)  
 // so there is no need to do anything here.  
 } 
 …. 
/** Messenger for communicating with service. */
 Messenger mService = null;
 
….
public void onServiceConnected(ComponentName className,
 IBinder service) {
 // This is called when the connection with the service has been
 // established, giving us the service object we can use to
 // interact with the service.  We are communicating with our
 // service through an IDL interface, so get a client-side
 // representation of that from the raw service object.
 mService = new Messenger(service);
 mCallbackText.setText("Attached.");
 
 // We want to monitor the service for as long as we are
 // connected to it.
 try {
 Message msg = Message.obtain(null,
 MessengerService.MSG_REGISTER_CLIENT);
 msg.replyTo = mMessenger;
 mService.send(msg);
 
 // Give it some value as an example.
 msg = Message.obtain(null,
 MessengerService.MSG_SET_VALUE, this.hashCode(), 0);
 mService.send(msg);
 } catch (RemoteException e) {
 // In this case the service has crashed before we could even
 // do anything with it; we can count on soon being
 // disconnected (and then reconnected if it can be restarted)
 // so there is no need to do anything here.
 }
 ….
本例實現瞭Client與Service 之間的雙向通信,因此在Client也定義瞭一個Messenger對象mMessenger,用於處理來自Service的消息。

有瞭 mService對象,就可以使用send向Service發送消息,如過需要Service 返回信息,可以定義message.replyTo 對象。

 
作者:mapdigit
 

發佈留言