To enable applications to communicate with each other, Android provides a unique implementation of the IPC (Inter process Communication, interprocess communication): Aidl (Android Interface Definition Language, Android Interface Definition language).
Build two Android projects, one client and one server (service provided).
This article will introduce the AIDL usage through a project that includes the service and client. It may be a little simpler, but burthen a lot.
This article provides a simple and understandable example of the use of aidl, divided into the client and the service side of the two parts, the client and the server to create a new Eclipse project, the implementation of the client to the server to send the request, the service side print log function.
The source structure of the client and server is as follows:
Note that because the package name of the client and server aidl files must be the same, and two packages with the same name will conflict when installed, so here is a trick, The package name is specified as com.styleflying in the client project's Androidmanifest.xml, so you'll see that the R.java in the Gen directory is com.styleflying instead of Com.styleflying.AIDL
Now the client and the server project create a new Aidl interface, the same package and file name must be the same. Two Aidl interface is the same, the content is as follows:
Package Com.styleflying.aidl;interface minterface{void invoktest ();}
Automatic compilation generates. java files as follows:
package com.styleflying.aidl;public interface minterface extends iinterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends Binder implements minterface { private static final string descriptor = "Com.styleflying.AIDL.mInterface"; /** Construct the stub at attach it to the Interface. */ public stub () { this.attachinterface (this, descriptor);} /** * cast an ibinder object into an com.styleflying.aidl.minterface interface, * generating A proxy if needed. */public static minterface asinterface (IBinder obj) { if ((obj==null)) {return null; } IInterface iin = (iinterface) obj.querylocalinterface (descriptor); if ((iin!=null) && (iin instanceof minterface)) {return (( Com.styleflying.AIDL.mInterface) iin); } return new Com.styleflying.AIDL.mInterface.Stub.Proxy (obj);} Public android.os.ibinder asbinder () { return this;} @Override public boolean ontransact (int code, parcel data, parcel Reply, int flags) throws remoteexception { switch (Code) {case interface_transaction: reply.writestring (descriptor); return true;case transaction_invoktest: data.enforceinterface (descriptor); this.invoktest (); reply.writenoexception (); return true; } return super.ontransact (code, data, reply, flags);} private static class proxy implements minterface { Private ibinder mremote; proxy (ibinder remote) {mRemote = remote; } public ibinder asbinder () {return mremote; } public string getinterfacedescriptor ( ) {return DESCRIPTOR; } public void Invoktest () throws RemoteException {Parcel _data = parcel.obtain (); Parcel _reply = parcel.obtain (); Try { _data.writeinterfacetoken ( descriptor); mremote.transact (Stub.transaction_invoktest, _data, _reply, 0); _reply.readexception ();} Finally { _reply.recycle (); _data.recycle ();} } } static final int TRANSACTION_invokTest = ( ibinder.first_call_transaction + 0); } public Void invoktest () throws remoteexception;}
package com.styleflying.aidl;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.view.view.onclicklistener;import android.widget.button;import android.widget.toast;import com.styleflying.R;public class mAIDLActivity extends Activity {private static final string tag = "Aidlactivity";p rivate button btnok;private Button btncancel;private button btncallback;private void log (STRING STR) {LOG.D ( TAG, "----------" + str + "----------");} Minterface mservice;private serviceconnection mconnection = new serviceconnectioN () {public void onserviceconnected (componentname classname,ibinder service) {Log ("Connect service "); Mservice = minterface.stub.asinterface (service);} Public void onservicedisconnected (componentname classname) {Log ("Disconnect service"); mservice = null;}}; /** called when the activity is first created. */ @Override public void oncreate (bundle savedinstancestate) { super.oncreate (savedinstancestate); Setcontentview (R.layout.main); btnOk = (Button) Findviewbyid (R.ID.BTN_OK); btnCancel = (Button) Findviewbyid (r.id.btn_cancel); btnCallBack = (BuTton) Findviewbyid (r.id.btn_callback); btnok.setonclicklistener (New onclicklistener () { public void onclick (VIEW V) { Bundle args = new bundle (); intent Intent = new intent ("Com.styleflying.AIDL.service"); intent.putextras (args); bindservice (Intent,mConnection, Context.bind_auto_create); } }); btncancel.setonclicklistener (New onclicklistener () { public void onclIck (view v) { unbindservice (mconnection); } }); btncallback.setonclicklistener (New onclicklistener () { public void onclick (VIEW V) {    TRY{        LOG.I (TAG, "Current Thread id = " + thread.currentthread (). GetId ()); Mservice.invoktest (); } catch (remoteexception e) { } } }); }}
When the client executes the Bindservice, after the service is successfully bound, it will callback Mconnection's onserviceconnected () and return the communication interface IBinder to the server, which IBinder is the service Onbind () When returning the IBinder, see Maidlservice.java.
In onserviceconnected (), the client successfully obtains the server-side communication interface, which is actually a local proxy object, which exists in the client process space, the client interacts only with the proxy object, and the real IPC communication is the local proxy object and the server-side communication.
Maidlservice.java as follows:
Package com.styleflying.aidl;import android.app.service;import android.content.intent;import android.os.IBinder;import android.os.Looper;import android.os.RemoteException;import android.util.log;import android.widget.toast;public class maidlservice extends service{ private static final string tag = "AIDLService"; private void log (STRING STR) {log.i (TAG, "----------" + str + "----------"); } public void oncreate () { Log ("service created"); } public void onstart ( Intent intent, int startid) {Log ("service started id = " + startId ), } public ibinder onbind (Intent t) {Log ("service on bind "); Return&nbsP;mbinder; } public void ondestroy () {Log ("service on destroy "); Super.ondestroy (); } public boolean onunbind (intent intent) {Log ("Service on unbind"); Return super.onunbind (Intent); } public void onrebind (Intent intent) {Log (" Service on rebind "); Super.onrebind (intent); } private final minterface.stub mbinder = new minterface.stub () {public void invoktest () throws RemoteException { // TODO AUTO-GENERATED METHOD STUB    LOG.E (tag, "remote call from client! current thread id = " + thread.currentthread (). GetId ());} };}
Note that the Onbind () function returns the Mbinder, and Mbinder implements the Minterface.stub, implements the Minterface interface, and performs the operation of printing the log.
The entire interaction process is as follows:
1) The client obtains the handle of the service (local proxy object) through the binding service;
2) The client executes the onclick (), invokes the local proxy object's Invoktest () function, and the local proxy object calls Mremote.transact () to make a remote invocation request (see Minterface.java);
3) The server Response Ontransact () executes this.invoktest () and returns the execution results;
Because the client communicates only with the local proxy object, the service handle, and the proxy object does true IPC operations, the IPC process is transparent to the client, invoking the remote operation as if it were a local operation. When the client calls Transact (), the service description dscription is written to data, which is verified when the client ontransact, and cannot communicate if two are different. The dscription is automatically generated based on the Minterface package name and interface name, which is why the minterface.aidl in both projects is in the same package.
In this process, MINTERFACE.AIDL serves as a bridge, providing a unified communication interface between the client and the server, enabling the client and the server to communicate successfully.
The process of specific communication transact and Ontransact is also the process of using binder to drive communication, which is not much described here.
Finally, the androidmanifest.xml of two works
<?xml version= "1.0" encoding= "Utf-8"? ><manifest xmlns:android= "http// Schemas.android.com/apk/res/android " package=" com.styleflying " android:versioncode= "1" android:versionname= "1.0" > <application android:icon= "@drawable/icon" android:label= "@string/app _name "> <activity android:name=". Aidl.maidlactivity " android:label= "@string/app_name" > <intent-filter> <action android:name= "Android.intent.action.MAIN" /> &nBsp; <category android:name= "Android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minsdkversion= "8" /></manifest>
<?xml version= "1.0" encoding= "Utf-8"? ><manifest xmlns:android= "http// Schemas.android.com/apk/res/android " package=" Com.styleflying.AIDL " android:versioncode= "1" android:versionname= " 1.0 "> <application android:icon=" @drawable/icon " android:label=" @string /app_name "> <service android:name=". MAIDLService " > <intent-filter> <action android:name= " Com.styleflying.AIDL.service " /> <category android:name= "Android.intent.category.DEFAULT" /> </intent-filter> </service> </application> <uses-sdk android:minsdkversion= "8" /> </manifest>
Android Aidl Example