Android application process-to-process communication: Messenger usage and source code analysis, androidmessenger

Source: Internet
Author: User

Android application process-to-process communication: Messenger usage and source code analysis, androidmessenger
1. Background

This knowledge point is a low product. At the beginning, I want to analyze it as a knowledge point in the previous article "Explanation of Android Asynchronous Message Processing Mechanism and source code analysis, however, after thinking about it, I thought it was time to analyze the inter-process communication analysis. However, let's take it out and write an analysis.

People are familiar with Message and Handler, but it is estimated that some people are not very often used in Messenger, and even worse, they can make the Messenger misspelled as Messager, thinking that the Message has added an r, of course, there are many articles about Messenger on the Internet, but my personal analysis summary is always personal. Haha. Let's get down to the truth.

Messenger implements IPC communication. The actual principle is that AIDL is used for communication, but unlike AIDL, Messenger uses Handler to process communication, therefore, it is thread-safe (concurrent processing is not supported). The AIDL we usually use is non-thread-safe (concurrent processing is supported ). Therefore, in most cases, we do not need to process exaggerated processes for concurrent communication. Therefore, it is easier to choose Messenger than AIDL.

[Craftsman if water http://blog.csdn.net/yanbober reprint please indicate the source. Click to start Android technical exchange]

2. Basic instance

Before analyzing the source code, let's look at a Demo example. The core logic is that the client process client sends a message to the remote process on the server. After receiving the message, the server process completes the processing and then sends a message back to the client, the entire process is implemented using the Messenger and Handler. The details are as follows:

Project Android management file:

<? Xml version = "1.0" encoding = "UTF-8"?> <Manifest xmlns: android = "http://schemas.android.com/apk/res/android" package = "com. example. yanbo. myapplication "> <application android: allowBackup =" true "android: icon =" @ mipmap/ic_launcher "android: label =" @ string/app_name "android: theme = "@ style/AppTheme"> <activity android: name = ". mainActivity "android: label =" @ string/app_name "> <intent-filter> <action android: name =" android. intent. action. MAIN "/> <ca Tegory android: name = "android. intent. category. LAUNCHER"/> </intent-filter> </activity> <! -- ": Remote" indicates that a new process is automatically created in an application when the service is required. "remote" indicates that a global process is created, different applications share the process --> <service android: name = ". remoteService "android: process =": remote "> <intent-filter> <action android: name =" com. remote. remoteService "/> </intent-filter> </service> </application> </manifest>

Remote source code of an independent process server in the project:

/*** Service */public class RemoteService extends Service {public static final int MSG_TAG_REMOTE = 0x110; public static final int MSG_TAG_CLIENT = 0x111; private Messenger mRemoteMessenger; private RemoteHandler mRemoteHandler; private int mCounter = 0; @ Override public void onCreate () {super. onCreate (); mRemoteHandler = new RemoteHandler (); // instantiate a Messenger to pass in the current Handler mRemoteMessenger = New Messenger (mRemoteHandler) ;}@ Override public IBinder onBind (Intent intent) {return (mRemoteMessenger = null )? Null: mRemoteMessenger. getBinder ();} private class RemoteHandler extends Handler {@ Override public void handleMessage (Message msg) {switch (msg. what) {case MSG_TAG_REMOTE: // to send the message back to the client, obtain the Messenger clientMessenger = msg set on the client. replyTo; if (clientMessenger! = Null) {try {// note that the first parameter of the obtain is explained in the previous article because the parameter target cannot be serialized to clientMessenger. send (Message. obtain (null, MSG_TAG_CLIENT, ++ mCounter, 0);} catch (RemoteException e) {e. printStackTrace () ;}} break; default: super. handleMessage (msg); break ;}}}}

Client code of an independent process client in the project:

Public class MainActivity extends Activity {private TextView mTextView; private Messenger mRemoteMessenger = null; private Messenger mClientMessenger; private ClientHandler mClientHandler; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); mTextView = (TextView) findViewById (R. id. content_show); // mClientHandle R = new ClientHandler (); mClientMessenger = new Messenger (mClientHandler); bindService (new Intent (this, RemoteService. class), connection, Context. BIND_AUTO_CREATE) ;}@ Override protected void onDestroy () {super. onDestroy (); unbindService (connection);} private ServiceConnection connection = new ServiceConnection () {@ Override public void onServiceConnected (ComponentName name, IBinder service) {m RemoteMessenger = new Messenger (service); // pay attention to the first parameter of the obtain. The previous article explains Message message = Message. obtain (null, RemoteService. MSG_TAG_REMOTE); message. replyTo = mClientMessenger; try {mRemoteMessenger. send (message);} catch (RemoteException e) {e. printStackTrace () ;}@ Override public void onServiceDisconnected (ComponentName name) {}}; private class ClientHandler extends Handler {@ Override public vo Id handleMessage (Message msg) {switch (msg. what) {case RemoteService. MSG_TAG_CLIENT: if (mTextView! = Null) {mTextView. setText (msg. arg1 + "") ;}break; default: super. handleMessage (msg); break ;}}}}

Let's look at it. This is a super simple Messenger application scenario. The specific process is as follows:

I believe there is no need to explain anything with this picture. This is enough to understand.

[Craftsman if water http://blog.csdn.net/yanbober reprint please indicate the source. Click to start Android technical exchange]

3. Analyze the Messenger source code

The above example shows that, without considering concurrency, Messenger is superior to AIDL in terms of code volume, engineering structure, and complexity. In this case, let's take a look at the source code of the Messenger class. Let's take a look at the entire core code of the Messenger class, and then explain it in detail. As follows:

/*** Link Handler to manage the Messenger class for sending and receiving messages across processes * You Can See That Messenger is a Messenger, is an Object */public final class Messenger implements Parcelable {// is actually a remote MessengerService AIDL interface private final IMessenger mTarget; // create a Messenger pointing to the target Handler, then, send the Messenger message as Handler's sendMessage public Messenger (Handler target) {mTarget = target. getIMessenger () ;}// send messages across processes, usually using Message. obtain () fills in the message Parameter. You can also use new public void send (Message message) throws RemoteException {mTarget. send (message) ;}// get the Messenger Binder, which is generally used on the remote end to obtain the public IBinder getBinder () {return mTarget. asBinder () ;}// if the two messengers are equal, it indicates that the Handler public boolean equals (Object otherObj) {if (otherObj = null) {return false ;} try {return mTarget. asBinder (). equals (Messenger) otherObj ). mTarget. asBinder ();} catch (ClassCastException e) {} return false ;}...... // obtain the same Messenger object as getBinder. It is generally used on the client to obtain public Messenger (IBinder target) {mTarget = imesget. stub. asInterface (target );}}

Using the global preview of the Messenger class and the above examples, we believe you have noticed that Messenger has two constructors: public Messenger (Handler target) and public Messenger (IBinder target ), obviously you already know that the parameter Handler is the remote process instance method, while the parameter IBinder is the client process instance method. In this case, let's start by getting the constructor public Messenger (Handler target) of the Messenger object from the server. The Code is as follows:

public Messenger(Handler target) {    mTarget = target.getIMessenger();}

The constructor calls the getIMessenger method of Handler. The source code of this method in Handler is as follows:

Public class Handler {...... // actually, for a Handler object, getIMessenger obtains the Messenger as a singleton mode object final IMessenger getIMessenger () {synchronized (mQueue) {if (mMessenger! = Null) {return mmesimp;} // obtain the Messenger implementation class MessengerImpl object mMessenger = new MessengerImpl (); return mMessenger ;}} in singleton mode ;}} // We can see that this is actually the AIDL private final class MessengerImpl extends IMessenger of Messenger. stub {public void send (Message msg) {// The send method actually transfers the sendMessage of Handler to send the Message Handler. this. sendMessage (msg );}}......}

As you can see, getIMessenger is a singleton object for every Handler object, and the Implementation class of this imesler object is MessengerImpl. You can also see that MessengerImpl is IMessenger. stub implementation class, this IMessenger. stub is actually an AIDL file that uses aapt to automatically generate a server interface subclass under our gen or build directory. Now, let's check the AIDL file (frameworks/base/core/java/android/OS/imesidl. aidl ):

Package android. OS; import android. OS. message;/** @ hide */oneway interface IMessenger {// you can see that the preceding MessengerImpl implements the Remote send interface void send (in Message msg) of Messenger );}

Now I understand that mTarget In the Messenger class is actually the imesipc remote IPC interface MessengerImpl in the single example of Handler.

Next, let's take a look at the onBind implementation in the Service. It has redeployed the getBinder method of Messenger. The source code of this method is as follows:

public IBinder getBinder() {    return mTarget.asBinder();}

As you can see, asBinder actually returns this, that is, itself, that is, the Messenger in Service is returned to the client through the onBind method.

Now we return to the client code of the above instance. We can find that the first task of the client process is to bind it with the remote process Service and then obtain the remote Messenger object instance. The constructor is as follows:

public Messenger(IBinder target) {    mTarget = IMessenger.Stub.asInterface(target);}

Hold the grass, isn't that how we get the server object at ordinary times? Yes. In this way, the client gets the Messenger object of the server. It seems that the client has a new object, but it is not.

Then there is the sending process. The message in the sending process is first serializable and then sent through the send method of Messenger. We have also analyzed this send method, the implementation is sent through the sendMessage method of Handler, so no more explanations are given, and the Handler and Message processes analyzed previously are returned.

In general, we can find that Messenger is not very high-end. Frankly speaking, it is just a second encapsulation of AIDL and then a combination of Handler to make it easier for users to use.

The principle of the entire Messenger is as follows:

[Craftsman if water http://blog.csdn.net/yanbober reprint please indicate the source. Click to start Android technical exchange]

4. Messenger Summary

After analyzing the Messenger, I believe I have understood what is going on, and I also know how to select a solution between AIDL and Messenger.

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.