Android uses AIDL to implement inter-process communication. androidaidl

Source: Internet
Author: User
Tags mremote

Android uses AIDL to implement inter-process communication. androidaidl

To enable applications to communicate with each other, Android provides an unique implementation of IPC (Inter Process Communication): AIDL (Android Interface Definition Language, android Interface Definition Language ).

In Android, each Application is executed in its own process and cannot be directly called to other Application resources. This is also in line with the concept of "sandbox. Therefore, in Android, some operations are restricted when an application is executed, such as memory access, sensor access, and so on. In this way, the system can be protected to the maximum extent, so that applications do not "do what they want ". What should we do if we sometimes need to interact between applications? Therefore, Android needs to implement the IPC protocol. However, this protocol is still a bit complex, mainly because the data management system (data transmission between processes or threads) needs to be implemented ). To temporarily reduce this problem, Android implements our own IPC, that is, AIDL.


AIDL (Android Interface Definition Language) is an Interface Definition Language. The compiler uses *. the description of the aidl file generates Java code that complies with the communication protocol. You do not need to write this complicated code by yourself. You only need to call it when necessary, in this way, we can complete inter-process communication.


AIDL is a lightweight Implementation of IPC and uses the syntax that is familiar to Java developers. Android also provides a tool to automatically create Stub (class architecture and class skeleton ). To communicate between applications, follow these steps:
1. Define an AIDL Interface
2. Implement Stub for the remote Service
3. Expose the service to the customer Program

4. Client call


Next, I will demonstrate the most basic process for operating AIDL.


1. Create a project

First, we need to build a server project, so:

In the com. scott. aidl package, create a common File (New-> File) namedIPerson. aidl. This file defines a "greeting" method:

    package com.scott.aidl;      interface IPerson {          String greet(String someone);      }  
Once the file is saved, the Android AIDL tool will Gen/com/scott/aidlThis folder automatically generates the corresponding IPerson. javaThis file. Because it is automatically generated, no changes are required. This file contains Stub, We will implement this Stub for our remote service. Formatted code:

    package com.scott.aidl;            public interface IPerson extends android.os.IInterface {          /** Local-side IPC implementation stub class. */          public static abstract class Stub extends android.os.Binder implements com.scott.aidl.IPerson {                            private static final java.lang.String DESCRIPTOR = "com.scott.aidl.IPerson";                    /** Construct the stub at attach it to the interface. */              public Stub() {                  this.attachInterface(this, DESCRIPTOR);              }                    /**              * Cast an IBinder object into an com.scott.aidl.IPerson interface,              * generating a proxy if needed.              */              public static com.scott.aidl.IPerson asInterface(android.os.IBinder obj) {                  if ((obj == null)) {                      return null;                  }                  android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);                  if (((iin != null) && (iin instanceof com.scott.aidl.IPerson))) {                      return ((com.scott.aidl.IPerson) iin);                  }                  return new com.scott.aidl.IPerson.Stub.Proxy(obj);              }                    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_greet: {                      data.enforceInterface(DESCRIPTOR);                      java.lang.String _arg0;                      _arg0 = data.readString();                      java.lang.String _result = this.greet(_arg0);                      reply.writeNoException();                      reply.writeString(_result);                      return true;                  }                  }                  return super.onTransact(code, data, reply, flags);              }                    private static class Proxy implements com.scott.aidl.IPerson {                  private android.os.IBinder mRemote;                        Proxy(android.os.IBinder remote) {                      mRemote = remote;                  }                        public android.os.IBinder asBinder() {                      return mRemote;                  }                        public java.lang.String getInterfaceDescriptor() {                      return DESCRIPTOR;                  }                        public java.lang.String greet(java.lang.String someone) throws android.os.RemoteException {                      android.os.Parcel _data = android.os.Parcel.obtain();                      android.os.Parcel _reply = android.os.Parcel.obtain();                      java.lang.String _result;                      try {                          _data.writeInterfaceToken(DESCRIPTOR);                          _data.writeString(someone);                          mRemote.transact(Stub.TRANSACTION_greet, _data, _reply, 0);                          _reply.readException();                          _result = _reply.readString();                      } finally {                          _reply.recycle();                          _data.recycle();                      }                      return _result;                  }              }                    static final int TRANSACTION_greet = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);          }                public java.lang.String greet(java.lang.String someone) throws android.os.RemoteException;      }  

The outline view of this file is as follows:

The abstract internal class Stub in the IPerson interface inherits android. OS. the Binder class implements the IPerson interface in the aidl file. The more important method is the asInterface (IBinder) method. This method converts an IBinder-type object to the IPerson type, generate a proxy object to return results if necessary.


2. implement remote services

First, we create a new class in the com. scott. aidl package named AIDLService. java.

    package com.scott.server;            import android.app.Service;      import android.content.Intent;      import android.os.IBinder;      import android.os.RemoteException;      import android.util.Log;            import com.scott.aidl.IPerson;            public class AIDLService extends Service {                private static final String TAG = "AIDLService";                    IPerson.Stub stub = new IPerson.Stub() {              @Override              public String greet(String someone) throws RemoteException {                  Log.i(TAG, "greet() called");                  return "hello, " + someone;              }          };                    @Override          public IBinder onBind(Intent intent) {              Log.i(TAG, "onBind() called");              return stub;          }                    @Override          public boolean onUnbind(Intent intent) {              Log.i(TAG, "onUnbind() called");              return true;          }                    @Override          public void onDestroy() {              super.onDestroy();              Log.i(TAG, "onDestroy() called");          }      }  
To implement our services, we need OnBindMethod returns IBinderClass Object (stub instance), so that the caller obtains IPerson. Stub is our instance. This IBinderClass objects represent the implementation of remote services. To implement this service, we need to use the automatically generated subclass. IPerson. Stub. Here, we must also implement the greet method defined in the AIDL file.


Of course, to make the Service take effect, we also need to make some configuration work in AndroidManifest. xml for other processes to access:

    <service android:name=".AIDLService">          <intent-filter>              <action android:name="android.intent.action.AIDLService" />                   <category android:name="android.intent.category.DEFAULT" />          </intent-filter>      </service>  
Now the server has been completed.


3. Client call

Next we should complete the work of the client. I have created a client project,

We only need to copy the IPerson. aidl file to the corresponding directory. the compiler will also generate the corresponding IPerson. java file, which is no different from the server. In this way, the server and client are unified in the communication protocol. We mainly work in MainActivity.

    package com.scott.client;            import android.app.Activity;      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.util.Log;      import android.view.View;      import android.widget.Button;      import android.widget.Toast;            import com.scott.aidl.IPerson;            public class MainActivity extends Activity {                private Button bindBtn;          private Button greetBtn;          private Button unbindBtn;                private IPerson person;          private ServiceConnection conn = new ServiceConnection() {                    @Override              public void onServiceConnected(ComponentName name, IBinder service) {                  Log.i("ServiceConnection", "onServiceConnected() called");                  person = IPerson.Stub.asInterface(service);              }                    @Override              public void onServiceDisconnected(ComponentName name) {                  //This is called when the connection with the service has been unexpectedly disconnected,                  //that is, its process crashed. Because it is running in our same process, we should never see this happen.                  Log.i("ServiceConnection", "onServiceDisconnected() called");              }          };                @Override          public void onCreate(Bundle savedInstanceState) {              super.onCreate(savedInstanceState);              setContentView(R.layout.main);                    bindBtn = (Button) findViewById(R.id.bindBtn);              bindBtn.setOnClickListener(new View.OnClickListener() {                  @Override                  public void onClick(View v) {                      Intent intent = new Intent("android.intent.action.AIDLService");                      bindService(intent, conn, Context.BIND_AUTO_CREATE);                                            bindBtn.setEnabled(false);                      greetBtn.setEnabled(true);                      unbindBtn.setEnabled(true);                  }              });                    greetBtn = (Button) findViewById(R.id.greetBtn);              greetBtn.setOnClickListener(new View.OnClickListener() {                  @Override                  public void onClick(View v) {                      try {                          String retVal = person.greet("scott");                          Toast.makeText(MainActivity.this, retVal, Toast.LENGTH_SHORT).show();                      } catch (RemoteException e) {                          Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();                      }                  }              });                    unbindBtn = (Button) findViewById(R.id.unbindBtn);              unbindBtn.setOnClickListener(new View.OnClickListener() {                  @Override                  public void onClick(View v) {                      unbindService(conn);                                            bindBtn.setEnabled(true);                      greetBtn.setEnabled(false);                      unbindBtn.setEnabled(false);                  }              });          }      }  

From the code, we can see that we want to rewrite the onServiceConnected method in ServiceConnection to convert the IBinder type to our IPerson type.

Now we have the last step left. This step is also the most critical, that is, binding the services we need. We define "android. intent. action. the identifier of AIDLService is bound to its service, so that the client and the server implement a communication connection, and we can call the "greeting" method in IPerson.


Iv. Result Display

Finally, paste several client demos.

The initial interface is displayed in sequence. Click the bindService interface, click the greet interface, and click the unbindService interface.

The operation logs are as follows:


V. Summary

The data types supported by AIDL are somewhat different from those supported by Java interfaces:
1. All basic types (int, char, etc)
2. String, List, Map, CharSequence, and other classes
3. Other AIDL Interface Types
4. All Parcelable classes


The final effect of AIDL is to make the communication between IPC as simple as calling a function. It automatically helps you complete the series of troubles of parameter serialization and sending and parsing the returned data. What you need to do is to write an interface file, and then use the aidl tool to convert it to another java file. This file is placed in each of the service and client programs. The service program inherits IxxxxService. Stub and implements the logic code in the function interface.

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.