Android aidl mechanism Case Study

Source: Internet
Author: User

Android aidl mechanism Case Study


After studying android during this time, I encountered aidl which was often mentioned and used in teaching videos. Then I found some materials on the Internet and wrote some cases for analysis, if I have written some deviations from the explanation, I hope you can help me to correct your opinions.

AIDL is an interface description file used to implement RPC on the Android platform. during compilation, aapt will automatically generate interfaces and objects for IPC according to the rules. As a user, you only need to: 1. implement interfaces on the server Service; 2. obtain the interface object when bindService and onServiceConnected are on the client. The interfaces here are all the interfaces described in AIDL. Other details are in the source code file of the same name generated by AIDL.

My implementation case is to get the information of a book from the server:

Package com. edify. bluenfcserver. myservice; import java. util. date; import android. annotation. suppressLint; import android. OS. parcel; import android. OS. parcelable;/*** @ Description write an object class step: * 1. implement the Pracelable interface * 2. you need to define a Parcelable. creator CREATOR object * 3. at the same time, you need to create an aidl file * @ Author monkey * @ Date 5:22:02 on January 1, September 4, 2014 */@ SuppressLint ("ParcelCreator") public class BookInfo implements Parcelable {private int id; Private String name; private String author; private float price; private Date product; public BookInfo (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 getAutho R () {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. price = price; this. product = product ;}@ Overridepublic int describeContents () {retu Rn 0;}/*** indicates the object serial number * dest is the destination object to be written to. * flags indicates the identifier of the object serial number. * Note that, the write order must be exactly the same as that read in the createFromParcel method. For example, if name is first written here, * in createFromParcel, you must first read name */@ Overridepublic void writeToParcel (Parcel dest, int flags) {dest. writeInt (id); dest. writeString (name); dest. writeString (author); dest. writeFloat (price); dest. writeValue (product); // write data of the date type}/*** this constant must be declared inside the entity class for serial number transfer. The constant name can only be a CREATOR, and the type must also be * Parcelable. Creator
 
  
*/Public static final Parcelable. Creator
  
   
CREATOR = new Parcelable. Creator
   
    
() {/*** Based on the Parcel object of the serial number, the reverse serial number is the original object * The read order must be the same as that of writeToParcel */public BookInfo createFromParcel (Parcel in) {int id = in. readInt (); String name = in. readString (); String author = in. readString (); float price = in. readFloat (); Date product = (Date) in. readValue (this. getClass (). getClassLoader (); return new BookInfo (id, name, author, price, product);} public BookInfo [] newArray (int size) {return new BookInfo [size] ;}};}
   
  
 

Client 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 Ndroid. 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 configuration file. private class MyServiceConnection Implements ServiceConnection {@ Overridepublic void onServiceConnected (ComponentName name, IBinder service) {Log. I ("notification", "link successful! "); 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 o NClick (View v) {switch (v. getId () {case R. id. button1: Intent intent = new Intent (actionName); bindService (intent, connection, Context. BIND_AUTO_CREATE); break; case R. id. button2: Intent intent2 = new Intent (actionName2); // establish a connection: Step 1: send a request to the server for bindService (intent2, new MyBookInfoServiceConnection (), Context. BIND_AUTO_CREATE); break ;}// creates a connection object with the server, which bridges private class MyBookInfoServiceConnection implements Servic EConnection {// establish a connection: Step 3 @ Overridepublic void onServiceConnected (ComponentName, IBinder service) {// determine whether the connection is in the same process, if yes, the returned result is the same object. If not, the returned result is a proxy object/*** for intra-process communication, there is no need for aidl mechanism to handle it * This is actually to judge whether the communication is in the same process or cross-process, because the object returned by the same process is Service *. the object returned by onBind (), and this object must implement the interface * (otherwise, it will be messy !). Therefore, if it is only in the same process, it does not go through the Binder process IPC *, but directly returns the object provided by the Service and calls its method directly, therefore, there is no restriction on the Parcelable object! * That is to say, in the same process, AIDL actually becomes like this: * that is, it directly returns the Service. the onBind () object is actually the same as the first method mentioned above *: The method for directly implementing the Binder object is the same *, and other code is redundant. Therefore, as previously suggested, if it is only in the same process, you can directly use the Binder, and there is no need to create an AIDL file. * In different processes *, the client Stub. asInterface returns a Stub. Proxy object and calls the print method on it. The server only executes the Stub *. onTransact () method, and then transfers it to the print method of the Service. * When cross-process operations are performed, you must use the IPC-related methods and mechanisms of the Binder object *. The client must implement the Binder. A Remote Method * is used by the client. The server must implement the Binder. onTransact * () to respond to the method requested by the client. For upper-layer users, use transact * () to send the function information (parameters, identifiers, and switches). The rest is the work of the Binder. * There are a lot of internal details, however, the onTransact * () method of the Binder on the server will be called. The function identifier is identified here, and the specific implementation is called, and the return value is returned, this completes the call of an IPC function. * When cross-process execution is required, only the following code is required. Unrelated code is removed: ** in fact, AIDL is used to Binder two methods: Binder. transact () and Binder. onTransact * () is encapsulated, and * is used by the Client and Server. Because the methods for implementing the transact () and onTransact () methods are basically the same *, you can use a template to generate specific code *. Theoretically, you only need to generate the transact () code for the Client and the onTransact * () code for the server, however, because the tool cannot accurately determine whether an application is a Client or a Server *, it generates all the code and stores it in a file. This is the automatically generated file you see. * Note that the Client-side Proxy combines the Binder object * and calls its transact () method. The server must inherit the Binder object * and overwrite the onTransact () method. What about Xiami? Because the Client initiates an IPC function Call *, it can directly Call the Binder method for IPC. The Server is passive. It is the IPC * call to be received, but the Service itself cannot know when the Call will come *. Therefore, a callback (onTransact () must be implemented to the Binder, so that the Binder can tell the Service when there is an IPC Call. * The principle and inner role of AIDL is to implement RPC (Remote Procedure * Call) on the Android platform, that is, Remote routine Call. RPC is one type of IPC, but it is a mechanism that calls Methods locally or in another process, or even on another host. * The purpose of RPC is to allow the program not to worry about the specific process or machine where the method is located *, just call it like a normal local method, the RPC mechanism handles all the details. RPC is generally described Using IDL (Interface Definition * Language). The implementation depends on the specific platform and Language. For more information about RPC and IDL, see Wikipedia. * AIDL provides RPC support for the Android platform: developers only need to define AIDL and perform some adaptation work. Then they can use these methods, * You do not need to worry about whether the method described in the interface is in the same process or in other processes. The details of these RPC implementations are handled by the Binder and system. */MyRemoteBookInfo = MyRemoteBookInfo. stub. asInterface (service); try {// establish a connection: Step 4: request data from the server, @ 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 ){}}}

Server 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: Step 2, return an object provided to the client operation server @ Overridepublic IBinder onBind (Intent intent) {return stub ;} /*** instantiate an object, which is the object provided to the client */private MyRemoteBookInfo. stub Stub = new MyRemoteBookInfo. stub () {/*** method not implemented by the Implementation interface * // The client request uses this method to determine the specific request operation @ Override public boolean onTransact (int code, android. OS. parcel data, an // establish a connection: Step 5. Call this method to return the data information of the server. Operation @ Overridepublic BookInfo getBookInfo (String tagName) throws RemoteException {return getBookInfoByTagName (tagName );}}; /*** @ Description method of the Service * @ Author monkey * @ param tagName * @ return * @ Return BookInfo */public BookInfo getBookInfoByTagName (String tagName) {Log. I ("getBookInfoByTagName ------------", tagName); if (tagName! = Null) {return new BookInfo (1, "", "Jin Yong", 100f, new Date ();} else {return new BookInfo (1, "文 ", "unknown", 200f, new Date ());}}}




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.