Android Aidl Instance Parsing

Source: Internet
Author: User
Tags server resume mremote

Aidl This technology in our development is generally not very common, although they also use Sina Weibo SSO login, the principle is to use aidl, but they have not done a complete aidl of the example, said embarrassing, so there is this simple article.
        aidl (Android Interface Description Language) is an excuse to describe the language, the compiler can generate a piece of code through the Aidl file, through a pre-defined interface to achieve the purpose of two process internal communication process. If you need to be in an activity, To access an object in another service, you need to first convert the object to a aidl-recognizable parameter (possibly multiple parameters), and then use Aidl to pass these parameters, and at the receiving end of the message, use these parameters to assemble the objects that you need.
plainly, Aidl is the definition of an interface, the client (the caller) through Bindservice to the remote server resume a connection, when the connection is established will return a IBinder object, the object is the binderproxy of the server binder, When the connection is established, the client wraps the Binderproxy object into a local proxy through the Asinterface function and assigns the Binderproxy object of the remote server to the Mremote field of the proxy class. is to execute a remote method call through Mremote. Need to have a deeper understanding of the binder mechanism, please go to Lao Luo's series of text bar, Android system interprocess communication Binder mechanism in the application framework Layer Java Interface Source code analysis. Let's look at a aidl instance.


Aidl Interface Declaration
in the SRC directory, create aCom.example.advanceandroid.aidl the package, and then create a ilogin.aidl file under the package, note that the file is created instead of the class or interface type. Declare the interface in Ilogin.aidl, with 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 joins public will prompt for errors. After writing, if Eclipse turns on automatic compilation, a Ilogin.java class is generated under Gen/com.example.advanceandroid.aidl, with the following content:

Package Com.example.advanceandroid.aidl;public Interface Ilogin extends android.os.iinterface{/** local-side IPC imple Mentation stub class. */public static abstract class Stub extends Android.os.Binder implements Com.example.advanceandroid.aidl.IL        Ogin {private 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 an IBinder object to an com.example.advanceandroid.aidl.ILogin * interface, Generati         Ng 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 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 Interf                    Ace_transaction: {reply.writestring (descriptor);                return true;                    } case Transaction_login: {//1, login request, execute 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, proxy in the login, through the binder mechanism to achieve 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, and another login () function is in the interface. But most importantly, there is a stub class that integrates the sub 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 IPC, and the obj is converted to the Ilogin type Otherwise, the obj will be wrapped by another auto-generated internal class proxy to assign it to the Mremote property in the proxy. The proxy class also implements the Ilogin interface, in the login () function, proxy passes the request and data to the server through the binder mechanism, such as note 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 Ilogin.aidl from the client's Com.example.advanceandroid.aidl package to the server, and if a custom type is used, the custom type needs to be available on both the client and the server side. After copying the aidl, the corresponding Ilogin.java file will be generated in Gen in the service-side program as well 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 execution of the This.login () function, through the client's analysis we know that when we call login () is actually through the mremote to the server to submit a Transaction_login request, So on both ends through the binder mechanism on the docking, we can simply understand the C/s mode.

The service side is not finished, the most important step when creating a service, the content is roughly as follows:

/*** Aidl Server Interface, Loginstubimpl implements 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;    }}

the service, which we named Loginservice, inherits from the service, and then constructs an inner class called Loginserviceimpl, which inherits from the automatically generated stub and then implements the login () method. In Loginservice, declare a ibinder field Mbinder:
IBinder mbinder = new Loginstubimpl ();
and the Mbinder object is returned in the Onbind function of Loginservice. That is, when the client establishes a connection to the server, the Onbind method is called to return the Mbinder object. The object IBinder obtained in the onserviceconnected function of the client's Serviceconnection class is the Loginservice object in Mbinder wrapped in binderproxy. So the This.login () function called in Ontransact in the server is actually the login () function in the called Loginstubimpl.

Register 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 Establish Connection

Add the following code to the activity:

 Serviceconnection mloginconnection = new Serviceconnection () {@Override public void onservicedisconnected (        ComponentName name) {LOG.D ("", "# # Aidl disconnected."); @Override public void onserviceconnected (componentname name, IBinder service) {LOG.D ("", "# # # Aidl OnSe     Rviceconnected.            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.le            Ngth_short). Show ();            } catch (RemoteException e) {e.printstacktrace ();    }        }    };        @Override protected void Onresume () {super.onresume (); The server-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 the client output log as follows:

09-02 10:40:54.662:d/(9589): # # Aidl onserviceconnected.     service:android.os.binderproxy09-02 10:40:54.662:d/(9589): # # after Asinterface: com.example.advanceandroid.aidl.ilogin$stub$proxy09-02 10:40:54.662:d/(9589): # # # Login: This is from Com.example.advanceandroid.aidl.loginservice$loginstubimpl the returned string

Can see lightthe service object in onserviceconnected (componentname name, IBinder service) is a binderproxy type and is packaged as a proxy type after asinterface conversion , but when invoked, the login () function in the server Loginstubimpl is executed. Therefore, the Loginstubimpl instance Mbinder is packaged as a binderproxy type by the server, then the proxy is packaged by the client, and the data transmission through the binder mechanism realizes the IPC.

Android Aidl Instance Parsing

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.