AIDL of Android IPC (1)

Source: Internet
Author: User
Tags mremote

AIDL of Android IPC (1)

IPC is short for Inter-Process Communication, that is, cross-Process Communication. In Android, there are multiple methods of cross-process communication, suchFile Sharing, UseContentProvider,Broadcast, AndSocket. In complex cases, the two methods are commonly used:MessengerAndAIDLThe underlying implementation of Messenger is AIDL.

First, let's take a look at the usage of AIDL.

Assume that we have a task of adding two numbers, and the client cannot complete the task (don't ask me why it cannot be completed =, let's just give it a question ~), The task must be handed over to the server in another process, and then the result of the task is obtained from the server.

First, create an AIDL interface as follows:

Android Studio automatically generates a path for it, such:

Declare an interface and an interface method that we want the server to implement in this file. As follows:

package com.vera.aidltest;interface IMyAdd {   int myAdd(int num_a,int num_b);}

Note that not all data types can be used in the AIDL file. The AIDL file only supports the following data types:

In Java, the basic data types are String, CharSequence List, and Map. The elements of the List and Map objects must be the APIS automatically generated by AIDL for Data Types supported by AIDL, even if it is in the same package) Implement android. OS. the object of the Parcelable interface class. import (import, even if it is in a package), you must create an AIDL file with the same name as it, and declare the class as Parcelable in the file.

After the interface is defined, the system generates a Java file for us. The AS file is in the app \ build \ generated \ source \ aidl \ debug directory. The generated code is AS follows:

package com.vera.aidltest;public interface IMyAdd extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.vera.aidltest.IMyAdd{private static final java.lang.String DESCRIPTOR = "com.vera.aidltest.IMyAdd";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.vera.aidltest.IMyAdd interface, * generating a proxy if needed. */public static com.vera.aidltest.IMyAdd asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.vera.aidltest.IMyAdd))) {return ((com.vera.aidltest.IMyAdd)iin);}return new com.vera.aidltest.IMyAdd.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{switch (code){case INTERFACE_TRANSACTION:{reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_myAdd:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();int _result = this.myAdd(_arg0, _arg1);reply.writeNoException();reply.writeInt(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.vera.aidltest.IMyAdd{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}@Override public int myAdd(int num_a, int num_b) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(num_a);_data.writeInt(num_b);mRemote.transact(Stub.TRANSACTION_myAdd, _data, _reply, 0);_reply.readException();_result = _reply.readInt();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_myAdd = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public int myAdd(int num_a, int num_b) throws android.os.RemoteException;}

The code looks very long and messy ...... Well, in this section, we will not look at it. We only need to know that it is an interface IMyAdd generated based on the AIDL file, including a static internal abstract class Stub (role, there is always something strange in this connection ......), The myAdd () method is declared. Why is it an abstract class? Because the IMyAdd interface is not actually implemented, Where can it be implemented? Of course it's our server.

Next, we can write the client and server code. So, what do we mean by the client and server here? In this example, they are respectively an Activity and a Service. Here we put them in the same application, but in some way they run in different processes. In more cases, they are not running in the same application. At this time, we need to copy the content of the entire aidl folder, because the AIDL Package Structure of the client and the server must be consistent, otherwise, the deserialization fails, and cross-process communication fails.

Now we start to write the server code. Create a Service named ServerService as follows:

package com.vera.aidltest;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class ServerService extends Service {   private Binder mBinder=new IMyAdd.Stub(){       @Override       public int myAdd(int num_a, int num_b) throws RemoteException {           int result=num_a+num_b;           Log.d("ServerService","the result of "+num_a+" and "+num_b+" is "+result);           return result;       }   };    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }}

ServerService is simple. It only creates a Binder object and returns it in the onBinder () method. This Binder object is the Stub object that implements the interface method. Well, now we can perform our operations happily in the myAdd () method. Here we just get the sum of num_a and num_ B, print it, and then return the result.

In addition, we need to set the Service in an independent process. Otherwise, how can we implement cross-process communication ~
Change AndroidManifest. xml as follows:


  

Now, the creation of the server is complete. Let's look at the client. What does the client do ?, Let's look at the Code:

package com.vera.aidltest;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;public class ClientActivity extends AppCompatActivity {    Button mButton;    private ServiceConnection myConnection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            IMyAdd mMyAdd=IMyAdd.Stub.asInterface(iBinder);            try {                int result=mMyAdd.myAdd(1,2);                Log.d("ClientActivity","get the result is "+result);            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_client);        mButton=(Button)findViewById(R.id.activity_client_mbutton);        mButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Intent intent=new Intent(ClientActivity.this,ServerService.class);                bindService(intent,myConnection, Context.BIND_AUTO_CREATE);            }        });    }    @Override    protected void onDestroy(){        unbindService(myConnection);        super.onDestroy();    }}

First, we created an anonymous ServiceConnection class and instantiated an object. Then, we set the bindService () method to bind the service after clicking the Button. The bindService () method receives three parameters. The first is the Intent object we created before this, the second is the Instance Object of ServiceConnection, and the third parameter is a flag, BIND_AUTO_CREATE indicates that the Service is automatically created after Activity and Service are bound. Then we override the onDestroy () method to unbind Activity and Service.

The focus is on the ServiceConnection Anonymous class created! In this class, we override the onServiceConnected () method and the onServiceDisconnected () method. These two methods are called when the Activity and Service are successfully bound and unbound respectively. In the onServiceConnected () method, we call the asInterface () method of Stub (). This method returns a Binder proxy object and converts it to an AIDL interface type object accepted by the client!

Okay, I got this object. Now I only need to call the method step by step. Let's try the number of rows equal to 1 + 2 ~

Run the program. After clicking the Button, view the log printing information, such:

In com. vera. in the aidltest process, the client prints the result 3, which is displayed on the com. vera. aidltest: in the remote process, the server prints 1 + 2 to 3 (poor English ......), Communication successful!

Well, let's summarize the specific steps:

First, create an AIDL file and define an interface in it. The interface should contain the declaration of the method we want the server to implement. Second, the Stub object that implements the method will be returned through the onBind () method on the server end, bind the service to the client, and override the method in the ServiceConnection class to obtain the Binder object, call the interface method of the server.

In this case, we have shielded a lot of details and only talked about how to use them. In the next section, tingzi will post more details. The first technical blog, please leave a message if anything is wrong ~

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.