Aidl examples of Android programming _android

Source: Internet
Author: User
Tags static class stub mremote

Generally speaking, the Aidl technology is not very common in our application development process, although Sina Weibo provides SSO login, but its principle is to use aidl. In this paper, the principle of aidl and its realization method are described in a complete instance form.

aidl (Android Interface Description Language) is an excuse to describe the language; The compiler can generate a piece of code through a aidl file that achieves the purpose of the two-process internal communication process through a predefined interface. If you need to be in an activity, To access an object in another service, you need to convert the object to an aidl identifiable parameter (possibly multiple parameters), and then use Aidl to pass these parameters and assemble them into the object you want at the receiving end of the message.

To put it bluntly, aidl is defined as an interface in which the client (caller) connects to a remote service-side resume via Bindservice, which returns a IBinder object that is the binderproxy of the server-side binder When the connection is established, The client wraps the Binderproxy object as a local proxy through the Asinterface function, assigns the Binderproxy object of the remote server to the Mremote field of the proxy class, and executes the remote method call through the mremote. There is a need for a deeper understanding of the binder mechanism, please refer to the Java Interface Source code analysis in the application framework layer for the binder mechanism of the inter-process communication of the Android system. Here we look at a aidl instance.

Aidl Interface Declaration

Create a com.example.advanceandroid.aidl package under the SRC directory, and then create a ilogin.aidl file under the package, noting that you create the file instead of the class or interface type. Declare an interface in Ilogin.aidl, as the following example:

Package com.example.advanceandroid.aidl;
Interface Ilogin {
    String login ();
}

Note that neither the interface nor the method declaration is public, and the method join public prompts for an error. When you finish writing, if Eclipse turns on automatic compilation, a Ilogin.java class is generated under Gen/com.example.advanceandroid.aidl, roughly as follows:

Package com.example.advanceandroid.aidl; Public interface Ilogin extends Android.os.IInterface {/** local-side IPC implementation stub class. */Public STA TIC abstract class Stub extends Android.os.Binder implements Com.example.advanceandroid.aidl.ILogin {Priva 
 
    Te static final java.lang.String descriptor = "Com.example.advanceandroid.aidl.ILogin"; /** construct the stub at attach it to the interface. 
    * * Public Stub () {this.attachinterface (this, descriptor);  /** * Cast a IBinder object into a com.example.advanceandroid.aidl.ILogin * interface, generating a 
     Proxy if needed.  */public static com.example.advanceandroid.aidl.ILogin asinterface (Android.os.IBinder obj) {if (obj = 
      NULL)) {return null; 
      } android.os.IInterface iin = Obj.querylocalinterface (descriptor); 
    if ((iin!= null) && (iin instanceof Com.example.advanceandroid.aidl.ILogin))) {    Return ((Com.example.advanceandroid.aidl.ILogin) iin); 
    Return to New Com.example.advanceandroid.aidl.ILogin.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_login: {//1, login request, execution is this.login (); 
          Data.enforceinterface (descriptor); 
          Java.lang.String _result = This.login (); 
          Reply.writenoexception (); 
          Reply.writestring (_result); 
        return true; 
    } return Super.ontransact (code, data, reply, flags); 
} private static class Proxy implements Com.example.advanceandroid.aidl.ILogin    {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 java.lang.String Login () throws Android.os.RemoteException//2, login in proxy, via B 
        Inder mechanism realizes IPC {Android.os.Parcel _data = Android.os.Parcel.obtain (); 
        Android.os.Parcel _reply = Android.os.Parcel.obtain (); 
        Java.lang.String _result; 
          try {_data.writeinterfacetoken (descriptor); 
          Mremote.transact (Stub.transaction_login, _data, _reply, 0); 
          _reply.readexception (); 
        _result = _reply.readstring (); 
          finally {_reply.recycle (); 
        _data.recycle (); 
      return _result; 
 
    } 
    }static final int transaction_login = (Android.os.IBinder.FIRST_CALL_TRANSACTION + 0); 
Public java.lang.String Login () throws android.os.RemoteException; 

 }

As you can see, the Ilogin interface is automatically generated in this class, with another login () function in the interface. But the most important thing is that it generates a stub class that integrates the binder class and implements the Ilogin interface. The most important thing in the stub is the Asinterface () function, in which the type of the obj parameter is judged, and if the obj is a local interface, it is considered not an IPC and the obj is converted to the Ilogin type Otherwise, the obj is wrapped by an automatically generated another internal class proxy, which is assigned to the Mremote property in the proxy. The proxy class also implements the Ilogin interface, and in the login () function, proxy passes the request and data to the server via the binder mechanism, as commented 2 in the code above. This is the client's job is done.

Service-Side Aidl interface

The server also needs to create a aidl file with the same name under the same package. We directly copy the client's Com.example.advanceandroid.aidl package ilogin.aidl to the server, and if the custom type is used, the custom type also needs to be available on both the client and the server. After copying the aidl, in the server program will also generate the corresponding Ilogin.java files in Gen, the same content as the client. The point here is to look at the Ontransact function, which is the comment 1 in the above code, and you can see that the This.login () function is executed at Case Transaction_login, meaning that when the client's Transaction_ is received Login request, the This.login () function is executed, and through the analysis of the client we know that when we call login () we actually submit a Transaction_login request via mremote to the server. So on both ends through the binder mechanism on the docking, we can simply understand the C/s mode.

The server is not finished, the most important step is to establish a service, the content is as follows:

/** 
* aidl Service Port Interface, Loginstubimpl implements the Ilogin interface. 
* 
* @author mrsimple/public 
class Loginservice extends Service { 
 
  /** 
   * 
   * 
  * * * * IBinder Mbinder = new Loginstubimpl (); 
 
  /** 
   * @author mrsimple 
   * 
  /class Loginstubimpl extends Stub { 
    @Override public 
    String Login () Throws RemoteException { 
      return "This is from" + This.getclass (). GetName () + "returned string"; 
    } 
  } 
   * * Returns the binder instance, the subclass of the stub that implements the Ilogin interface, which is Loginstubimpl 
   * [url=home.php?mod=space&uid=133757] @see [/ URL] Android.app.service#onbind (android.content.Intent) 
   */ 
  @Override public 
  ibinder Onbind (Intent Intent) {return 
    mbinder; 
  } 
} 

We name the service here as Loginservice, inherit from service, then build an inner class called Loginserviceimpl, which inherits from the automatically generated stub and implements the login () method. Declare a ibinder field in Loginservice Mbinder:

IBinder Mbinder = new Loginstubimpl ();

and returns the Mbinder object in the Loginservice onbind function. That is, when the client establishes a connection to the server, the Onbind method is invoked to return the Mbinder object, The object IBinder in the onserviceconnected function of the Serviceconnection class of the client is the Loginservice object in the Binderproxy wrapped Mbinder. So the This.login () function that is invoked in the ontransact in the server is actually the login () function in the called Loginstubimpl.

Register the Loginservice in the androidmanifest.xml of the server-side program as follows:

<!--aidl Server service--> 
<service android:name= "Com.example.advanceandroid.aidl.LoginService" > 
    <intent-filter> 
      <action android:name= "Com.example.advanceandroid.aidl.LoginService"/> 
    </intent-filter> 
</service> 

Client establishes a connection

Add the following code to the activity:

Serviceconnection mloginconnection = new Serviceconnection () {@Override public void onservicedisconnected (Co 
 
    Mponentname name) {LOG.D ("", "### aidl disconnected.");} @Override public void onserviceconnected (componentname name, IBinder service) {LOG.D ("", "###, Aidl ONSERVICEC   Onnected. 
 
      Service: "+ Service.getclass (). GetName ()); 
      Ilogin login = stub.asinterface (service); 
      LOG.D ("", "### after Asinterface:" + login.getclass (). GetName ()); 
        try {log.d ("", "### Login:" + login.login ()); Toast.maketext (Mainactivity.this, "onserviceconnected:" +//Login.login (),//Toast.length_short). 
      Show (); 
      catch (RemoteException e) {e.printstacktrace (); 
 
  } 
    } 
  }; 
 
    @Override protected void Onresume () {super.onresume (); 
    Service-side action Intent aidlintent = new Intent ("Com.example.advanceandroid.aidl.LoginService"); Bindservice (aidlintent, Mloginconnection, context.bind_auto_create); 
    } @Override protected void OnStop () {super.onstop (); 
  Unbind Unbindservice (mloginconnection); 

 }

Run

Run the server-side program first, and then when you start the client program, you can see that the client outputs the following log:

09-02 10:40:54.662:d/(9589): ### aidl onserviceconnected.   Service:android.os.BinderProxy 
09-02 10:40:54.662:d/(9589): ### after Asinterface: Com.example.advanceandroid.aidl.ilogin$stub$proxy 
09-02 10:40:54.662:d/(9589): ### Login: This is from String returned by Com.example.advanceandroid.aidl.loginservice$loginstubimpl 

You can see that the service object in the light onserviceconnected (componentname name, IBinder service) is Binderproxy type and is packaged as a proxy type after asinterface conversion , but when invoked, the login () function in the service-side Loginstubimpl is executed. Therefore, the Loginstubimpl instance Mbinder is packaged by the service end as Binderproxy type, then is packaged by proxy of the client, and is transmitted through the binder mechanism to realize IPC.

I hope this article will help you to further understand the Android program.

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.