IPC Lightweight Implementation--aidl

Source: Internet
Author: User
Tags mremote

We understand aidl from three aspects:

1) Introduction

2) Definition

3) Example


An introduction

Aidi (Android Interface Definition language), which is a bridge used in Android to solve inter-process communication, its internal implementation is binder, is a lightweight implementation of the IPC mechanism, and provides tools for automatically creating stubs in Android.


Two definitions

Aidl can know from its name that it is a file of an interface type, but it differs from the interface defined in Java:

1) Different types of support:

Types supported by Aidl:

1, basic data type (int, long, char, etc.)

2,string, Charsequence, List (ArrayList), Map (HASHMAP), etc.

3, all objects that implement the Parcelable interface

4, all AIDL interfaces

2) In addition to the basic data types, custom parcelable objects and Aidl interfaces must display the import in, regardless of whether they are in the same package

3) In addition to the basic data types, the parameters of the other data types must be marked with the direction: in (input type), out (output type), inout (input and output type), in use to limit the direction of use, because in the bottom implementation is very expensive.


Three examples

1) Create a Aidl instance

First create a Javabean:car

Package Com.swun.tinama.aidl_demo;import android.os.parcel;import android.os.parcelable;/** * Created by Administrator on 2016/5/8.    */public class Car implements parcelable {public int getcarid () {return carid; } @Override Public String toString () {return "car{" + "carid=" + Carid + ", CA    Rname= ' + carname + ' \ ' + '} ';    } public void Setcarid (int carid) {This.carid = Carid;    } public String Getcarname () {return carname;    } public void Setcarname (String carname) {this.carname = Carname;    } private int Carid;    Private String Carname;        Protected Car (Parcel in) {Carid = In.readint ();    Carname = In.readstring ();        } public Car (int carid, String carname) {this.carid = Carid;    This.carname = Carname; public static final creator<car> Creator = new creator<car> () {@Override public Car Create Fromparcel (Parcel In) {return new Car (in);        } @Override Public car[] NewArray (int size) {return new car[size];    }    };    @Override public int describecontents () {return 0;        } @Override public void Writetoparcel (Parcel dest, int flags) {dest.writeint (Carid);    Dest.writestring (Carname); }}
Car class implements the parcelable, so that the car object can be passed in the aidl, since want to pass in Aidl to create a car.aidl file

Car.aidlpackage com.swun.tinama.aidl_demo;parcelable Car;
Then create an interface to manage car:

Icarfactory.aidlpackage Com.swun.tinama.aidl_demo;import Com.swun.tinama.aidl_demo. Car;import Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener;interface Icarfactorymanager {    void Addcar (in car car);    void remove (in car car);    List<car> getcars ();    void Registlistener (Ionnewcararrivedlistener listener);    void Unregistlistener (Ionnewcararrivedlistener listener);}
As can be seen, although the car class is and Icarfactorymanager is in a factory, but also to import car path, Ionnewcararrivedlistener is when the service in the car factory added into a car, Notifies the client that its implementation is:

Ionnewcararrivedlistener.aidlpackage Com.swun.tinama.aidl_demo;import Com.swun.tinama.aidl_demo. car;//Declare any non-default types here with import statementsinterface Ionnewcararrivedlistener {    /**     * Demons Trates some basic types that's can use as parameters     * and return values in Aidl.     *    /void basictypes (int anint, long along, Boolean aboolean, float afloat,            double adouble, String astring);    void onnewcararrived (in car car);}
When you click Build/make Project in Androidstudio, the corresponding Java file is generated under Gen:



We chose Ionnewcararrivedlist.java to look at the internal implementation:

/* * This file is auto-generated. Do not MODIFY. * Original file:e:\\git\\aidl_demo\\app\\src\\main\\aidl\\com\\swun\\tinama\\aidl_demo\\ Ionnewcararrivedlistener.aidl */package com.swun.tinama.aidl_demo;//Declare any non-default types here with Import Statementspublic interface Ionnewcararrivedlistener extends android.os.iinterface{/** local-side IPC implementation Stub class. */public static abstract class Stub extends Android.os.Binder implements Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener{private static final Java.lang.String descriptor = "Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener ";/** Construct the stub at attach it to the interface. */public Stub () {this.attachinterface (this, descriptor);} /** * Cast an IBinder object to an Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener interface, * Generating a proxy if needed. */public static Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener asinterface (Android.os.IBinder obj) {if ((Obj==null)) {return null;} Android.os.IInTerface iin = obj.querylocalinterface (descriptor); if ((Iin!=null) && (iin instanceof Com.swun.tinama.aidl_ Demo. Ionnewcararrivedlistener)) {return (Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener) iin);} return new Com.swun.tinama.aidl_demo. IOnNewCarArrivedListener.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.O S.remoteexception{switch (code) {case interface_transaction:{reply.writestring (descriptor); return true;} Case Transaction_basictypes:{data.enforceinterface (descriptor); int _arg0;_arg0 = Data.readint (); Long _arg1;_arg1 = Data.readlong (); Boolean _arg2;_arg2 = (0!=data.readint ()); float _arg3;_arg3 = Data.readfloat ();d ouble _arg4;_arg4 = Data.readdouble (); java.lang.String _arg5;_arg5 = data.readstring (); This.basictypes (_arg0, _arg1, _arg2, _arg3, _ARG4, _ARG5); Reply.writenoexception (); return true;} Case Transaction_onnewcararriVed:{data.enforceinterface (descriptor); Com.swun.tinama.aidl_demo. Car _arg0;if ((0!=data.readint ())) {_arg0 = Com.swun.tinama.aidl_demo. Car.CREATOR.createFromParcel (data);} else {_arg0 = null;} This.onnewcararrived (_arg0); reply.writenoexception (); return true;}} Return Super.ontransact (Code, data, reply, flags);} private static class Proxy implements Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener{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;}     /** * Demonstrates some basic types that's can use as parameters * and return values in Aidl.  */@Override public void basictypes (int anint, long along, Boolean aboolean, float afloat, double adouble, java.lang.String astring) throws Android.os.remoteexception{android.os.parcel _data = Android.os.Parcel.obtain (); Android.os.Parcel _ Reply = Android.os.Parcel.obtain (); try{_data.writeinterfacetoken (descriptor); _data.writeint (Anint); _data.writelong (along); _data.writeint (((ABoolean) ? (1):(0)); _data.writefloat (afloat); _data.writedouble (adouble); _data.writestring (astring); Mremote.transact ( Stub.transaction_basictypes, _data, _reply, 0); _reply.readexception (); finally {_reply.recycle (); _data.recycle ();}} @Override public void onnewcararrived (Com.swun.tinama.aidl_demo. Car car) throws Android.os.remoteexception{android.os.parcel _data = Android.os.Parcel.obtain (); Android.os.Parcel _ Reply = Android.os.Parcel.obtain (), try {_data.writeinterfacetoken (descriptor), if ((Car!=null)) {_data.writeint (1); Car.writetoparcel (_data, 0);} else {_data.writeint (0);} Mremote.transact (stub.transaction_onnewcararrived, _data, _reply, 0); _reply.readexception ();} finally {_reply.recycle (); _data.recycle ();}}} static final int transaction_basictypes = (Android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int transaction_ Onnewcararrived = (Android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}     /** * Demonstrates some basic types that's can use as parameters * and return values in Aidl. */public void basictypes (int anint, long along, Boolean aboolean, float afloat, double adouble, java.lang.String astring) Throws Android.os.remoteexception;public void Onnewcararrived (Com.swun.tinama.aidl_demo. Car car) throws android.os.RemoteException;}
First of all, all aidl are to inherit iinterface, it generates an inner class stub,stub is binder, so we return in the Service.onbind is a stub object, Asinterface () is to convert the binder object into the Aidl object we need, so that the service gives the client a burst of port, the client can get the binder from the Onbind, and then get the required Aidl object, This makes it possible to invoke methods in the remote service.

Asinterface:querylocalinterface () is to determine whether the client and the server are in the same process, and if so, get the binder on the server, or get the Stub.proxy object

Proxy is the true implementation of binder, when the client calls Onnewcararrived is called Proxt method, the method first will serialize the data into a binary stream, and then call the stub in the Transact (), Transact chooses to invoke the different methods in binder by using the identifier, the method in Binder is our own implementation in the service, this is to deserialize the data, all said custom classes to implement Parcelable.

Let's look at how the service and client are implemented:

Service

Package Com.swun.tinama.aidl_demo. Service;import Android.app.service;import Android.content.intent;import Android.os.*;import Android.support.annotation.nullable;import Android.util.log;import Com.swun.tinama.aidl_demo. Car;import Com.swun.tinama.aidl_demo. Icarfactorymanager;import Com.swun.tinama.aidl_demo. Ionnewcararrivedlistener;import Com.swun.tinama.aidl_demo.utils.myutils;import Java.util.List;import Java.util.concurrent.copyonwritearraylist;import java.util.concurrent.atomic.atomicboolean;/** * Created by Administrator on 2016/5/8.    */public class Carmanagerservice extends Service {private static final String TAG = "Carmanangerservice";    Private Atomicboolean Matomicboolean = new Atomicboolean (false);    Private copyonwritearraylist<car> mcarlist = new copyonwritearraylist<car> (); Private copyonwritearraylist<ionnewcararrivedlistener> mlisteners = new copyonwritearraylist<    Ionnewcararrivedlistener> (); Private Remotecallbacklist<ionnewcararrivedlistener> mlisteners = new remotecallbacklist<ionnewcararrivedlistener> (); Private IBinder binder = new Icarfactorymanager.stub () {@Override public void Addcar (car car) throws Remote        Exception {mcarlist.add (car);        } @Override public void remove (car car) throws RemoteException {mcarlist.remove (car);        } @Override Public list<car> getcars () throws remoteexception {return mcarlist;            } @Override public void Registlistener (Ionnewcararrivedlistener listener) throws RemoteException {//            Mlisteners.add (listener);        Mlisteners.register (listener);            } @Override public void Unregistlistener (Ionnewcararrivedlistener listener) throws RemoteException {//            Mlisteners.remove (listener);        Mlisteners.unregister (listener);    }    };        @Override public void OnCreate () {super.oncreate (); McarlisT.add (New Car (1, "Audi"));        Mcarlist.add (New Car (2, "Volkswagen"));        LOG.I (TAG, Myutils.getcurrentprocessname (this));    New Thread (New Factorywroker ()). Start (); } Private class Factorywroker implements Runnable {@Override public void run () {while (!mato                    Micboolean.get ()) {try {thread.sleep (1000);                    int carid = mcarlist.size () + 1;                    Car car = new car (Carid, "new car#" + Carid);                Onnewcararrived (car);                } catch (Interruptedexception e) {e.printstacktrace ();                } catch (RemoteException e) {e.printstacktrace ();    }}}} @Nullable @Override public ibinder onbind (Intent Intent) {return binder; private void onnewcararrived (car car) throws RemoteException {log.i (TAG, "new Car arrived" + car.tostring ())        ;        Mcarlist.add (car); /*for (Ionnewcararrivedlistener listener:mlisteners) {listener.onnewcararrived (car);        }*/int count = Mlisteners.beginbroadcast ();            for (int i = 0; i < count; i++) {Ionnewcararrivedlistener listener = Mlisteners.getbroadcastitem (i);            if (listener! = null) {listener.onnewcararrived (car);    }} mlisteners.finishbroadcast ();        } @Override public void OnDestroy () {Matomicboolean.set (true);    Super.ondestroy (); }}

Client

Package Com.swun.tinama.aidl_demo;import Android.content.componentname;import Android.content.intent;import Android.content.serviceconnection;import Android.os.bundle;import Android.os.handler;import Android.os.IBinder; Import Android.os.remoteexception;import Android.support.v7.app.appcompatactivity;import Android.util.Log;import Android.view.view;import Com.swun.tinama.aidl_demo. Service.carmanagerservice;import Com.swun.tinama.aidl_demo.utils.myutils;import Java.util.List;public Class    Mainactivity extends Appcompatactivity {private static final String TAG = "mainactivity";    Private Handler Mhandler = new Handler ();    Private Icarfactorymanager Mtmpfactorymanager;  Private Ionnewcararrivedlistener Cararrivedlistener = new Ionnewcararrivedlistener.stub () {@Override public void basictypes (int anint, long along, Boolean aboolean, float afloat, double adouble, String astring) throws Remoteexcep tion {} @Override public void onnewcararrived (final Car car) throws RemoteException {mhandler.post (new Runnable () {@Override publi                c void Run () {log.i (TAG, "receive notification of new car!" + car.tostring ());        }            });    }    }; Private Serviceconnection mserviceconnection = new Serviceconnection () {@Override public void Onserviceconn ected (componentname name, IBinder service) {Icarfactorymanager Carfactorymanager = ICarFactoryManager.Stub.asI            Nterface (service);                try {mtmpfactorymanager = Carfactorymanager;                List<car> cars = Carfactorymanager.getcars ();                Printcarinformation (cars);                Cars.add (New Car (3, "Mercedes-Benz"));                Printcarinformation (cars);            Carfactorymanager.registlistener (Cararrivedlistener);            } catch (RemoteException e) {e.printstacktrace (); }} @Override public void OnservicedisconneCTED (componentname name) {}};    void Printcarinformation (List<car> cars) {log.i (TAG, cars.tostring ());        } @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (R.layout.activity_main);    LOG.I (TAG, Myutils.getcurrentprocessname (this)); } @Override protected void OnDestroy () {/*if (Mtmpfactorymanager! = null && mtmpfactorymanager.asbin                Der (). Isbinderalive ()) {try {log.i (TAG, "logout listener!");            Mtmpfactorymanager.unregistlistener (Cararrivedlistener);            } catch (RemoteException e) {e.printstacktrace ();        }}*/Unbindservice (mserviceconnection);    Super.ondestroy (); } public void Unregist (View v) {if (Mtmpfactorymanager! = null && mtmpfactorymanager.asbinder (). Isbinde      Ralive ()) {try {log.i (TAG, "logout listener!");          Mtmpfactorymanager.unregistlistener (Cararrivedlistener);            } catch (RemoteException e) {e.printstacktrace ();        }}} public void CLICK (View v) {Intent Intent = new Intent (this, carmanagerservice.class);    Bindservice (Intent, mserviceconnection, bind_auto_create); }}
In order to mimic the service configuration in a different process in Androidmanifest.xml:

<service            android:name= ". Service.carmanagerservice "            android:process=": Second "></service>
This allows you to see that communication between different processes is achieved through log:




You can see that the client will not receive a message when we unregist the button

The source code has been submitted to GitHub Https://github.com/522363215/AIDL_demo/tree/master


Warm tips:

1) When using list, we can use Copyonwritearraylist, which implements the list interface, and it supports concurrent read/write

2) The processing of data in binder is serialized and deserialized, and if we want to obtain the same object through binder processing, we can use Remotecallbacklist, which automatically implements the function of thread synchronization internally.

Here, Aidl's introduction is over, thank you for watching!






IPC Lightweight Implementation--aidl

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.