Service官方教程(8)Bound Service示例之2-跨进程使用Messenger
Compared to AIDL
When you need to perform IPC, using a Messenger for your interface is simpler than implementing it with AIDL, because Messenger queues all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the service, which must then handle multi-threading.
For most applications, the service doesn't need to perform multi-threading, so using a Messenger allows the service to handle one call at a time. If it's important that your service be multi-threaded, then you should use AIDL to define your interface.
Using a Messenger
If you need your service to communicate with remote processes, then you can use a Messenger to provide the interface for your service. This technique allows you to perform interprocess communication (IPC) without the need to use AIDL.
Here's a summary of how to use a Messenger:
使用Messenger的步骤:
- The service implements a
Handlerthat receives a callback for each call from a client. - The
Handleris used to create aMessengerobject (which is a reference to theHandler). - The
Messengercreates anIBinderthat the service returns to clients fromonBind(). - Clients use the
IBinderto instantiate theMessenger(that references the service'sHandler), which the client uses to sendMessageobjects to the service. - The service receives each
Messagein itsHandler—specifically, in thehandleMessage()method.
In this way, there are no "methods" for the client to call on the service. Instead, the client delivers "messages" (Message objects) that the service receives in its Handler.
注意,这种方式下,服务端没有函数给客户端调用。它们只能发送消息。
Here's a simple example service that uses a Messenger interface:
1 public class MessengerService extends Service { 2 /** Command to the service to display a message */ 3 static final int MSG_SAY_HELLO = 1; 4 5 /** 6 * Handler of incoming messages from clients. 7 */ 8 class IncomingHandler extends Handler { 9 @Override 10 public void handleMessage(Message msg) { 11 switch (msg.what) { 12 case MSG_SAY_HELLO: 13 Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); 14 break; 15 default: 16 super.handleMessage(msg); 17 } 18 } 19 } 20 21 /** 22 * Target we publish for clients to send messages to IncomingHandler. 23 */ 24 final Messenger mMessenger = new Messenger(new IncomingHandler()); 25 26 /** 27 * When binding to the service, we return an interface to our messenger 28 * for sending messages to the service. 29 */ 30 @Override 31 public IBinder onBind(Intent intent) { 32 Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); 33 return mMessenger.getBinder(); 34 } 35 }
Notice that the handleMessage() method in the Handler is where the service receives the incoming Message and decides what to do, based on the what member.
All that a client needs to do is create a Messenger based on the IBinder returned by the service and send a message using send(). For example, here's a simple activity that binds to the service and delivers the MSG_SAY_HELLO message to the service:
1 public class MessengerActivity extends Activity { 2 /** Messenger for communicating with the service. */ 3 Messenger mService = null; 4 5 /** Flag indicating whether we have called bind on the service. */ 6 boolean mBound; 7 8 /** 9 * Class for interacting with the main interface of the service. 10 */ 11 private ServiceConnection mConnection = new ServiceConnection() { 12 public void onServiceConnected(ComponentName className, IBinder service) { 13 // This is called when the connection with the service has been 14 // established, giving us the object we can use to 15 // interact with the service. We are communicating with the 16 // service using a Messenger, so here we get a client-side 17 // representation of that from the raw IBinder object. 18 mService = new Messenger(service); 19 mBound = true; 20 } 21 22 public void onServiceDisconnected(ComponentName className) { 23 // This is called when the connection with the service has been 24 // unexpectedly disconnected -- that is, its process crashed. 25 mService = null; 26 mBound = false; 27 } 28 }; 29 30 public void sayHello(View v) { 31 if (!mBound) return; 32 // Create and send a message to the service, using a supported 'what' value 33 Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); 34 try { 35 mService.send(msg); 36 } catch (RemoteException e) { 37 e.printStackTrace(); 38 } 39 } 40 41 @Override 42 protected void onCreate(Bundle savedInstanceState) { 43 super.onCreate(savedInstanceState); 44 setContentView(R.layout.activity_messenger); 45 } 46 47 @Override 48 protected void onStart() { 49 super.onStart(); 50 // Bind to the service 51 bindService(new Intent(this, MessengerService.class), mConnection, 52 Context.BIND_AUTO_CREATE); 53 } 54 55 @Override 56 protected void onStop() { 57 super.onStop(); 58 // Unbind from the service 59 if (mBound) { 60 unbindService(mConnection); 61 mBound = false; 62 } 63 } 64 }
Notice that this example does not show how the service can respond to the client. If you want the service to respond, then you need to also create a Messenger in the client. Then when the client receives the onServiceConnected() callback, it sends a Message to the service that includes the client's Messenger in the replyTo parameter of the send() method.
You can see an example of how to provide two-way messaging in the MessengerService.java (service) and MessengerServiceActivities.java (client) samples.

浙公网安备 33010602011771号