This period of time in learning Android, the results encountered in the teaching video often mention and use Aidl, and then found some information on the Internet, wrote some cases to analyze and analyze, if I write and explain some deviation, hope can be pointed out to correct their humble opinion. <p><span style= "FONT-SIZE:12PX;" >aidl is an interface description file that is used to implement the Android platform above the rpc,aapt at compile time automatically according to the rules generated for the IPC interface and objects, and as a user only need: 1. Implement Interface on Server service, 2. Gets the interface object when the client bindservice,onserviceconnected. The interface here is the interface described in Aidl, the other details in the aidl generated by the same name source file </span></p><p><span style= "FONT-SIZE:12PX;" > The case that I realized is to get a book information from the server:</span></p>
Package Com.edify.bluenfcserver.myservice;import Java.util.date;import Android.annotation.suppresslint;import Android.os.parcel;import android.os.parcelable;/** * @Description write an entity class step: * 1. Implement Pracelable interface * 2. You need to define a parcelable.creator Creator Object * 3. Also to create a aidl file * @Author Monkey * @Date September 4, 2014 PM 5:22:02 */@SuppressLint ("Parcelcreator") public class BookInfo Implemen TS parcelable {private int id;private string name;private string author;private float price;private Date product;public Bo Okinfo (Parcel in) {}public int getId () {return ID;} public void setId (int id) {this.id = ID;} Public String GetName () {return name;} public void SetName (String name) {this.name = name;} Public Date getproduct () {return product;} public void Setproduct (Date product) {this.product = product;} Public String Getauthor () {return author;} public void Setauthor (String author) {this.author = author;} public float GetPrice () {return price;} public void Setprice (float price) {this.price = Price;} public BookInfo (int ID, String name, string author, float price, Date product) {super (); this.id = Id;this.name = Name;this.author = AUTHOR;THIS.P Rice = Price;this.product = product;} @Overridepublic int describecontents () {return 0;} /** * The object serial number * Dest is the object that is about to be written. Flags about the way the object's serial number is marked * Note here that the order of writing is exactly the same as the order in which the Createfromparcel method is read. For example, this is the first name written here, * then the name must be read first/@Overridepublic void Writetoparcel (Parcel dest, int flags) in Createfromparcel { Dest.writeint (ID);d est.writestring (name);d est.writestring (author);d est.writefloat (Price);d Est.writevalue ( product);//write a date type of data}/** * Be sure to declare the constant inside the entity class that you want to pass the serial number to. The constant name can only be Creator, and the type must also be * parcelable.creator<t> */public static final parcelable.creator<bookinfo> Creator = New Parcelable.creator<bookinfo> () {/*** * Based on the parcel object of the serial number, the inverse sequence number is the original entity object * The readout order is the same as the Writetoparcel write order */public BookInfo Createfromparcel (Parcel in) {int id = in.readint (); String name = In.readstring (); String author = in.readstring (); Float price = In.readfloat ();D ate product = (Date) in.readvalue (thiS.getclass (). getClassLoader ()); return new BookInfo (ID, name, author, price, product);} Public bookinfo[] NewArray (int size) {return new bookinfo[size];};}
The client's code:
Package Com.edify.bluenfc;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.menu;import Android.view.view;import Android.view.view.onclicklistener;import Android.widget.Button; Import Android.widget.textview;import Com.edify.bluenfcserver.beauty;import com.edify.bluenfcserver.RemoteBeauty; Import Com.edify.bluenfcserver.myservice.bookinfo;import Com.edify.bluenfcserver.myservice.MyRemoteBookInfo; Import Com.edify.bluenfcserver.myservice.myremotebookinfo.stub;public class Mainactivity extends Activity implements Onclicklistener {TextView TextView; Button button; String actionname = "Com.edify.bluenfcserver.remoteservice"; String actionName2 = "Com.edify.bluenfcserver.myservice.myRemoteService"; Remotebeauty remotebeauty;private Myremotebookinfo MyremotEbookinfo;private TextView textview2;private View button2; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); TextView = (TextView) Findviewbyid ( R.ID.TEXTVIEW1); textView2 = (TextView) Findviewbyid (r.id.textview2); button = (button) Findviewbyid (R.id.button1); Button2 = (Button) Findviewbyid (R.id.button2); Button.setonclicklistener (this); Button2.setonclicklistener (this);} Service.querylocalinterface ("Com.edify.bluenfcserver.RemoteBeauty");//Getpackagemanager () : Provides a way to query the configuration in the manifest file private class Myserviceconnection implements Serviceconnection {@Overridepublic void onserviceconnected (componentname name, IBinder service) {LOG.I ("notification", "link succeeded!") "); remotebeauty = RemoteBeauty.Stub.asInterface (service); try {Beauty Beauty = Remotebeauty.getbeauty (); Textview.settext ("Beauty name:" + beauty.getname () + "Age:" + beauty.getage () + "Gender:" + beauty.getsex ());} catch (RemoteException e) {e.printstacktrace ();}} @Overridepublic VOID onservicedisconnected (componentname name) {}}myserviceconnection connection = new myserviceconnection (); @ overridepublic void OnClick (View v) {switch (V.getid ()) {case R.id.button1:intent Intent = new Intent (actionname); bindser Vice (intent, Connection, context.bind_auto_create); break;case r.id.button2:intent intent2 = new Intent (ACTIONNAME2); /Establish Connection: First step, send request Bindservice (Intent2, New Mybookinfoserviceconnection (), context.bind_auto_create) to the service end; Establish link object with server, bridge private class Mybookinfoserviceconnection implements Serviceconnection {//Establish connection: Third step @overridepublic void onserviceconnected (componentname name, IBinder service) {//determines if the communication is within the same process, if it is the same object returned, if it is not then the proxy object is returned/** * If it is an in-process communication, there is no need for a aidl mechanism to deal with it. This is actually a matter of judging whether this communication is in the same process or across processes, because the same process returns the object that is returned by service *. Onbind (), and this object is bound to implement the interface * (otherwise hairy!) )。 So, if only in the same process, not the binder process IPC *, but directly return the service provided by the object, directly call its methods, so there will be no object must be parcelable restrictions! * That is, when in the same process the aidl actually becomes this: * that is, it is directly returning the object of the Service.onbind (), which is actually the first way to do this: the direct implementation of binder objects is the same way *, the rest of the code is all superfluous. Therefore, as suggested earlier, if you are only using binder directly in the same process, it is not necessary to create a aidl file. * When in a different process *, the client Stub.asinterface returns a Stub.proxy object, calling the Print method on it. The server only executes the stub *. Ontransact () method, and then it is transferred to the service's Print method. * When crossing processes, use the IPC-related methods and mechanisms of binder objects *. The client needs to implement the Binder.transact () method to execute a remote method *, which is used by the client, while the server needs to implement Binder.ontransact * () in response to the method requested by the client. For upper-level users, use Transact * () to send information about the function (parameters, logos, and switches), leaving the binder to work *, with a lot of detail inside, but eventually calling the Ontransact * () method of the server binder, The identity of the function is identified, then the specific implementation is called, and the return value is returned, so that an IPC function call is completed. * When cross-process, only the following code is required, remove extraneous code: * * In fact, the role of Aidl is two methods of Binder: Binder.transact () and Binder.ontransact * () to encapsulate, * For use by client side and server side. Because the way the Transact () and Ontransact () methods are implemented is essentially the same *, you can use a template to generate specific code *. In theory, you only need to generate transact () related code for the client side, generate the Ontransact * () code for the server, but because the tool cannot determine exactly whether an application is client or server-side *, it generates all the code. Placed in a file. This is the auto-generated file you see. * It is also important to note that the client proxy is a combination binder object *, called its Transact () method, and the server must inherit the Binder object *, overwrite the Ontransact () method. What about the shrimp? Because the client is actively initiating the IPC function call *, it can directly invoke the binder method to carry out the IPC. And the server is passive, is to receive incoming IPC * call, but the service itself can not know when call will come *, you must implement a callback (Ontransact ()) to the binder so that the binder tells the service when an IPC call comes in. * Principle and insider Aidl's role is to implement RPC (remote Procedure * call) on the Android platform, which is also called as a remoting routine. RPC is one of the IPC's, but it is a mechanism to invoke methods on a local or another process, or even on another host. * The purpose of RPC is to let the program do not worry about the method is in which process or where the machine above *, as normal local methods to call, the RPC mechanism will handle all the specifics. RPC is generally described by IDL (Interface Definition * Language), which depends on the specific platform and language. You can refer to Wikipedia for more information about RPC and IDL. * Aidl provides RPC support for the Android platform: Developers only need to define AIDL, do some relevant adaptation work, and then can use these methods, * do not specifically care about the interface description of the method null whether in the same process or in other processes. The details of these RPC implementations are handled by binders and systems. */myremotebookinfo = MyRemoteBookInfo.Stub.asInterface (service); try {//Establish connection: Fourth step to server-side request data, @Override public bookinfo// Getbookinfo (java.lang.String tagName)//Call this method to request data: Mremote.transact (stub.transaction_getbookinfo,//_data, _ Reply, 0); BookInfo BookInfo = Myremotebookinfo.getbookinfo ("I am a tagname"); Textview2.settext (bookinfo.tostring ());} catch (RemoteException e) {e.printstacktrace ();}} @Overridepublic void onservicedisconnected (componentname name) {}}}
Service-Side code:
Package Com.edify.bluenfcserver.myservice;import Java.util.date;import Android.app.service;import Android.content.intent;import Android.os.ibinder;import Android.os.remoteexception;import Android.util.Log;public Class Myremoteservice extends Service {//Establish a connection: The second step is to return an object that is provided to the client Operation server @overridepublic IBinder onbind (Intent Intent) { return stub;} /** * Instantiates an object that is the object provided to the client */private myremotebookinfo.stub Stub = new Myremotebookinfo.stub () {/** * Implements an interface not implemented method *///client This is the way to judge the specific request that Operation @override Public boolean ontransact (int code, ANDROID.OS.PARCEL data, an//establish connection: Fifth step By calling this method back to the server side of the data information, Operation @overridepublic BookInfo getbookinfo (String tagName) throws RemoteException {return Getbookinfobytagname (tagName);}};/ * * @Description the method of service itself * @Author Monkey * @param tagName * @return * @Return BookInfo */public BookInfo getbookinfobyt AgName (String tagName) {log.i ("Getbookinfobytagname--------------", TagName), if (tagName! = null) {return new BookInfo ( 1, "Shong", "Jin Yong", 100f, New Date ()); Else{return New BookinfO (1, "Marsh", "Unknown", 200f, New Date ());}}}
Android's aidl mechanism case