If you need your service to communicate with remote processes, you can use a Messenger to provide interfaces for your service. This technology can be used to implement inter-process communication (IPC) without using AIDL ).
The following is an overview of how to use Messenger:
Service implements a Handler that receives the callback caused by each call from the client.
Handler is used to create a Messenger object (it is a reference of Handler ).
Messenger creates an onBind () from the service and returns it to the IBinder of the client.
The client uses IBinder to instantiate this Messenger (it references the Handler of the service), and the client uses it to send a Message to the service.
The service receives each message in its Handler-specific, In the handleMessage () method.
In this way, no method can be called by the client in the service. The client sends the "Message" (Message object) received by the service in its Handler ).
The following is an example of using the Messenger interface for a service:
[Java] public class MessengerService extends Service {
/** Command to display a message for the service */
Static final int MSG_SAY_HELLO = 1;
/**
* Process messages from the client.
*/
Class IncomingHandler extends Handler {
@ Override
Public void handleMessage (Message msg ){
Switch (msg. what ){
Case MSG_SAY_HELLO:
Toast. makeText (getApplicationContext (), "hello! ", Toast. LENGTH_SHORT). show ();
Break;
Default:
Super. handleMessage (msg );
}
}
}
/**
* The object that we publish to the client so that it can send messages to IncomingHandler
*/
Final Messenger mMessenger = new Messenger (new IncomingHandler ());
/**
* When bound to the service, we return the interface pointing to our messenger.
*/
@ Override
Public IBinder onBind (Intent intent ){
Toast. makeText (getApplicationContext (), "binding", Toast. LENGTH_SHORT). show ();
Return mmesder. getBinder ();
}
}
Public class MessengerService extends Service {
/** Command to display a message for the service */
Static final int MSG_SAY_HELLO = 1;
/**
* Process messages from the client.
*/
Class IncomingHandler extends Handler {
@ Override
Public void handleMessage (Message msg ){
Switch (msg. what ){
Case MSG_SAY_HELLO:
Toast. makeText (getApplicationContext (), "hello! ", Toast. LENGTH_SHORT). show ();
Break;
Default:
Super. handleMessage (msg );
}
}
}
/**
* The object that we publish to the client so that it can send messages to IncomingHandler
*/
Final Messenger mMessenger = new Messenger (new IncomingHandler ());
/**
* When bound to the service, we return the interface pointing to our messenger.
*/
@ Override
Public IBinder onBind (Intent intent ){
Toast. makeText (getApplicationContext (), "binding", Toast. LENGTH_SHORT). show ();
Return mmesder. getBinder ();
}
}
Note that the handleMessage () method in Handler is where the service receives and processes messages.
All the client has to do is create a Messenger object based on the IBinder returned by the service and send a message using its send. for example, the following example shows how to bind an actvity to a service and send the MSG_SAY_HELLO command to the service:
[Java] public class ActivityMessenger extends Activity {
/** The Messenger that communicates with the service */
Messenger mService = null;
/** Indicates whether the tag has been bound to the service */
Boolean mBound;
/**
* Main Interface interaction class with service
*/
Private ServiceConnection mConnection = new ServiceConnection (){
Public void onServiceConnected (ComponentName className, IBinder service ){
// It is called when the connection with the service has been established. It can be used
// The object that interacts with the service. We are using a Messenger to communicate with the service,
// Here we get the Messenger representative of a client from the original IBinder object
MService = new Messenger (service );
MBound = true;
}
Public void onServiceDisconnected (ComponentName className ){
// It is called when the connection to the service is accidentally disconnected -- that is, the service process crashes.
MService = null;
MBound = false;
}
};
Public void sayHello (View v ){
If (! MBound) return;
// Create and send a message to the service
Message msg = Message. obtain (null, MessengerService. MSG_SAY_HELLO, 0, 0 );
Try {
MService. send (msg );
} Catch (RemoteException e ){
E. printStackTrace ();
}
}
@ Override
Protected void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. main );
}
@ Override
Protected void onStart (){
Super. onStart ();
// Bind to service
BindService (new Intent (this, MessengerService. class), mConnection,
Context. BIND_AUTO_CREATE );
}
@ Override
Protected void onStop (){
Super. onStop ();
// Unbind from the service
If (mBound ){
UnbindService (mConnection );
MBound = false;
}
}
}
Public class ActivityMessenger extends Activity {
/** The Messenger that communicates with the service */
Messenger mService = null;
/** Indicates whether the tag has been bound to the service */
Boolean mBound;
/**
* Main service interface Interaction Class www.2cto.com
*/
Private ServiceConnection mConnection = new ServiceConnection (){
Public void onServiceConnected (ComponentName className, IBinder service ){
// It is called when the connection with the service has been established. It can be used
// The object that interacts with the service. We are using a Messenger to communicate with the service,
// Here we get the Messenger representative of a client from the original IBinder object
MService = new Messenger (service );
MBound = true;
}
Public void onServiceDisconnected (ComponentName className ){
// It is called when the connection to the service is accidentally disconnected -- that is, the service process crashes.
MService = null;
MBound = false;
}
};
Public void sayHello (View v ){
If (! MBound) return;
// Create and send a message to the service
Message msg = Message. obtain (null, MessengerService. MSG_SAY_HELLO, 0, 0 );
Try {
MService. send (msg );
} Catch (RemoteException e ){
E. printStackTrace ();
}
}
@ Override
Protected void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. main );
}
@ Override
Protected void onStart (){
Super. onStart ();
// Bind to service
BindService (new Intent (this, MessengerService. class), mConnection,
Context. BIND_AUTO_CREATE );
}
@ Override
Protected void onStop (){
Super. onStop ();
// Unbind from the service
If (mBound ){
UnbindService (mConnection );
MBound = false;
}
}
}
Note that this example does not demonstrate how the service responds to the client. if you want the service to respond to the client, you need to create a Messanger on the client. then, when the client receives the onServiceConnected () callback, it sends an information to the service. The message contains the client's Messenger object, which serves as the replyTo parameter of the send () method.
Compare AIDL
When you need to execute IPC, it is easier to use a Messenger for your interface than to use AIDL, because Messenger puts all service calls into the queue, A pure AIDL interface sends requests to the service in parallel, so that multi-thread processing is required.
For most applications, the service does not need to use multithreading, so using a Messenger allows the service to process only one request at a time. if multithreading is important to your service, you should use AIDL to define your interface.
From the column of nkmnkm