Reason for writing: The realization and understanding of communication across processes is an important part of Android's advanced. The following bloggers share some knowledge about IPC, their operations and their understanding of the process of learning IPC. This chapter uses Messenger to implement cross process communication, where bindservice the android IPC mechanism binding service implements local communication.
Introduction to cross-process
Before you introduce using Messenger to communicate across processes, understand the following questions: Why do you need to communicate across processes? Only the need to have the value of learning. I personally interpret different processes simply as different applications (with exceptions, for example, to open two or more processes in the same application). Since processes cannot share memory as threads, data communications cannot be as common as threads. You can use bundle, broadcasts, MESSENGER,AIDL, and sockets to communicate across processes in Android. This chapter utilizes messenger to implement single application multi process one-way communication and multi-application multi-process two-way communication respectively.
Messenger Introduction
Messenger is a way to implement a single request by using a message to communicate across processes, which is its pros and cons . Its underlying implementation is aidl (I will elaborate on the next chapter). Messenger's advantages are: Based on message, easy to use, support callback way, that is, server-side processing the growth task can interact with the client; you do not need to write aidl files.
Messenger usage process is as follows (reprint):
Single application multi-process one-way communication
Let's start with a single application in Android that opens multiple processes, and in fact, add <android:progress = "Remote (customizable)" > or < in the XML of the component in mainfests that you want to open a new process. android:progress = "package. Remote (can be customized)" > on the line. Such as:
<service android:name= ". Customservice "android:process=": Remote "/>
This allows the service to run in a new thread.
Service implementation
The following is a service-side code implementation that creates a handler object to handle the message sent by the client, and then creates a Messenger object that passes the handler object as a parameter, so we get a messenger. The following is the return of the binder object created by Getbinder () to the client (once the client gets the binder, it can be restored to Messenger). The processing information in handler is: Output toast when the what value of the resulting message is Msg_say_hello.
public class Customservice extends service{
static final int msg_say_hello = 1;
Implement a Handler
class Incominghandler extends handler{that can handle receiving information
@Override public
void Handlemessage ( Message msg) {
super.handlemessage (msg);
Switch (msg.what) {case
Msg_say_hello:
toast.maketext (Getapplicationcontext (), "hello!", toast.length_ Short). Show ();
break;
Default:
super.handlemessage (msg);
}}} The Messenger object received by the client is
final Messenger messenger = new Messenger (new Incominghandler ());
@Override public
IBinder onbind (Intent Intent) {
toast.maketext (Getapplicationcontext (), "binding!", Toast.length_short). Show ();
return Messenger.getbinder ();
}
Activity implementation
What we should do in the client is to get the Messenger object from the service (get in serviceconnection, see the previous article), and then create a message object that writes the data for the message. Note that the what in the message is consistent with the what in the handler object in the service end. Use this Messenger to send the message to the server via Send (), which enables one-way communication between the client and the server.
The specific code is as follows:
public class Mainactivity extends Appcompatactivity {private Button mbtstart;
Private Messenger messenger = null;
Private Boolean mbound;
Private TextView mtvmsg; Private Serviceconnection serviceconnection = new Serviceconnection () {@Override public void onserviceconnected (C
Omponentname name, IBinder service) {messenger = new Messenger (service);
Mbound = true;
@Override public void onservicedisconnected (componentname name) {messenger = null;
Mbound = false;
}
};
public void SayHello (View v) {if (!mbound) return;
Message msg = Message.obtain (null,customservice.msg_say_hello,0,0);
try{messenger.send (msg);
}catch (RemoteException e) {e.printstacktrace ();
} @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Mbtstart = (Button) Findviewbyid (R.id.bt_start); Mtvmsg = (TextView) finDviewbyid (R.ID.TV_MSG); Mbtstart.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (View v) {Inten
T intent = new Intent (Mainactivity.this,customservice.class);
Bindservice (New Intent (Mainactivity.this,customservice.class), serviceconnection, context.bind_auto_create);
}
});
} @Override protected void OnStop () {super.onstop ();
Unbind from the service if (mbound) {unbindservice (serviceconnection);
Mbound = false; }
}
}
The above process at first understanding may be somewhat abstract, more hands-on to deepen understanding.
Multi-application multi-process two-way communication
It still takes activity and service communications as an example, but this time we need to create two new module (ClientApp and Serviceapp), ClientApp in one activity, A service in Serviceapp (the start-up of an app that has no activity in its own way, Baidu). This is the case for two applications in two processes.
The following is an analysis of the use of Messenger in this case:
Service implementation
It is still the first to start with the service. The general idea is similar to the creation of the service above, but the difference is that this time we need to create a new Clientmessenger to enable the service to send a message to the client. There is this code in the handler of the service,
Clientmessenger = msg.replyto;//This message is created in the client
if (clientmessenger!=null) {message
msgtoclient = Message.obtain ();
Msgtoclient.what = Send_message_code;
Bundle Bundle = new Bundle ();
Bundle.putstring ("MSG", "Client, I received your message, this is my response to you, see?" ");
Msgtoclient.setdata (bundle);
try {
clientmessenger.send (msgtoclient);
} catch (RemoteException e) {
e.printstacktrace ();
}
}
The code above is used to respond to sending data to the client after receiving the data sent by the client. Note that the Clientmessenger = Msg.replyto is the Clientmessenger object that is bundled with MSG from the client. The Clientmessenger can be used to return data to the activity.
The detailed code is as follows:
public class MyService extends Service {private static final int receive_message_code = 0x0001;
private static final int send_message_code = 0x0002;
Private Messenger Clientmessenger = null;
Private Messenger Servicemessenger = new Messenger (new Servicehandler ());
@Override public IBinder onbind (Intent Intent) {return servicemessenger.getbinder ();
@Override public void OnCreate () {super.oncreate ();
@Override public void OnDestroy () {Super.ondestroy ();
Clientmessenger = null; Private class Servicehandler extends handler{@Override public void Handlemessage (msg) {super.
Handlemessage (msg);
if (msg.what = = Receive_message_code) {Bundle data = Msg.getdata ();
if (data!= null) {String str = data.getstring ("msg");
Toast.maketext (Getapplicationcontext (), "Service:i received": +str,toast.length_short). Show (); } Clientmessenger = msg.replyto;//this messAge is the IF (clientmessenger!=null) {Message msgtoclient = Message.obtain () created in the client.
Msgtoclient.what = Send_message_code;
Bundle Bundle = new Bundle (); Bundle.putstring ("MSG", "Client, I received your message, this is my response to you, see?"
");
Msgtoclient.setdata (bundle);
try {clientmessenger.send (msgtoclient);
catch (RemoteException e) {e.printstacktrace (); }
}
}
}
}
}
Activity implementation:
The main activity is to implement binding to send data and unbind two blocks of functionality. Binding sends an explicit intent (more than 5.0 does not support an implicit start service, see the startup process below) Bind the service, get the Messenger object when the binding succeeds, and use the object to send the Message object msg to the service, as shown above. One thing that is different here is that in order to enable service to get Clientmessenger, we have to manually associate MSG with Clientmessenger, namely: Msg.replyto = Clientmessenger;. In this way, the service can get the message that the activity sends, but also take the Clientmessenger. The Clientmessenger must be created first, and the method is consistent with one-way acquisition.
The detailed code is as follows:
public class Mainactivity extends appcompatactivity{private Button mbtbind;
Private Button Mbtunbind;
Private TextView mtvmsg;
private static final int send_message_code = 0x0001;
private static final int receive_message_code = 0x0002;
Private Boolean isbound = false;
Private String service_action = "Com.example.serviceapp.MyService";
Private Messenger Servicemessenger = null;
Private Messenger Clientmessenger = new Messenger (new ClientHandler ());
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Mbtbind = (Button) Findviewbyid (R.id.bt_bind);
Mbtunbind = (Button) Findviewbyid (R.id.bt_unbind);
Mtvmsg = (TextView) Findviewbyid (r.id.tv_msg); Mbtunbind.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (View v) {if (i
Sbound) {unbindservice (serviceconnection);
}
}
}); Mbtbind. Setonclicklistener (New View.onclicklistener () {@Override public void OnClick (View v) {if (!isbound) {
Intent Intent = new Intent ();
Intent.setaction (service_action);
Intent.addcategory (Intent.category_default);
Packagemanager pm = Getpackagemanager ();
Resolveinfo info = pm.resolveservice (intent,0);
if (info!= null) {String packagename = info.serviceInfo.packageName;
String serviceName = info.serviceInfo.name;
ComponentName componentname = new ComponentName (packagename,servicename);
Intent.setcomponent (componentname);
Bindservice (intent,serviceconnection,bind_auto_create);
}
}
}
}); Private Serviceconnection serviceconnection = new Serviceconnection () {@Override public void Onserviceconnect
Ed (componentname name, IBinder service) {Servicemessenger = new Messenger (service);
Isbound = true; Message msg = Message.obtain ();
Msg.what = Send_message_code;
Bundle data = new Bundle ();
Data.putstring ("msg", "Hello, MyService, I am client");
Msg.setdata (data);
Msg.replyto = Clientmessenger;
try {servicemessenger.send (msg);
catch (RemoteException e) {e.printstacktrace ();
@Override public void onservicedisconnected (componentname name) {Servicemessenger = null;
Isbound = false;
}
}; Private class ClientHandler extends handler{@Override public void Handlemessage (msg) {Super.handle
Message (msg);
if (msg.what = = Receive_message_code) {Bundle data = Msg.getdata ();
if (data!= null) {String str = data.getstring ("msg");
Mtvmsg.settext (str);
}
}
}
}
}
Summarize:
This piece may be difficult to understand, so I hope the reader will try to prepare for the later aidl to learn from the communication mode.