| page.title=Designing a Remote Interface Using AIDL |
| @jd:body |
| |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#implementing">Implementing IPC Using AIDL</a> |
| <ol> |
| <li><a href="#aidlsyntax">Create an .aidl File</a></li> |
| <li><a href="#implementtheinterface">Implementing the Interface</a></li> |
| <li><a href="#exposingtheinterface">Exposing Your Interface to Clients</a></li> |
| <li><a href="#parcelable">Pass by value Parameters using Parcelables</a></li> |
| </ol> |
| </li> |
| <li><a href="#calling">Calling an IPC Method</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| |
| <p>Since each application runs in its own process, and you can write a service that |
| runs in a different process from your Application's UI, sometimes you need to pass objects |
| between processes. On the Android platform, one process can not normally access the memory |
| of another process. So to talk, they need to decompose their objects into primitives that |
| the operating system can understand, and "marshall" the object across that boundary for you.</p> |
| |
| <p>The code to do that marshalling is tedious to write, so we provide the AIDL tool to do it |
| for you.</p> |
| |
| <p>AIDL (Android Interface Definition Language) is an <a |
| href="http://en.wikipedia.org/wiki/Interface_description_language">IDL</a> |
| language used to generate code that enables two processes on an Android-powered device |
| to talk using interprocess communication (IPC). If you have code |
| in one process (for example, in an Activity) that needs to call methods on an |
| object in another process (for example, a Service), you would use AIDL to |
| generate code to marshall the parameters.</p> |
| <p>The AIDL IPC mechanism |
| is interface-based, similar to COM or Corba, but lighter weight. It uses a proxy |
| class to pass values between the client and the implementation. </p> |
| |
| |
| <h2 id="implementing">Implementing IPC Using AIDL</h2> |
| <p>Follow these steps to implement an IPC service using AIDL.</p> |
| <ol> |
| <li><strong><a href="#aidlsyntax">Create your .aidl file</a> </strong>- This |
| file defines an interface (<em>YourInterface</em>.aidl) that defines the |
| methods and fields available to a client. </li> |
| <li><strong>Add the .aidl file to your makefile</strong> - (the ADT Plugin for Eclipse |
| manages this for you). Android includes the compiler, called |
| AIDL, in the <code>tools/</code> directory. </li> |
| <li><strong><a href="#implementtheinterface">Implement your interface methods</a></strong> - |
| The AIDL compiler creates an interface in the Java programming language from your AIDL interface. |
| This interface has an inner abstract class named Stub that inherits the |
| interface (and implements a few additional methods necessary for the IPC |
| call). You must create a class that extends <em>YourInterface</em>.Stub |
| and implements the methods you declared in your .aidl file. </li> |
| <li><strong><a href="#exposingtheinterface">Expose your interface to clients</a></strong> - |
| If you're writing a service, you should extend {@link |
| android.app.Service Service} and override {@link android.app.Service#onBind |
| Service.onBind(Intent)} to return an instance of your class that implements your |
| interface. </li> |
| </ol> |
| |
| <h3 id="aidlsyntax">Create an .aidl File</h3> |
| <p>AIDL is a simple syntax that lets you declare an interface with one or more |
| methods, that can take parameters and return values. These parameters and return |
| values can be of any type, even other AIDL-generated interfaces. <em>However, it |
| is important to note</em> that you <em>must</em> import all non-built-in types, |
| <em>even if they are defined in the same package as your interface</em>. |
| Here are the data types that AIDL can support: </p> |
| <ul> |
| <li>Primitive Java programming language types (int, boolean, etc) |
| — No <code>import</code> statement is needed. </li> |
| <li>One of the following classes (no <code>import</code> statements needed): |
| <ul> |
| <li><strong>String</strong></li> |
| <li><strong>List</strong> - All elements in the List must be one of the types |
| in this list, including other AIDL-generated interfaces and |
| parcelables. List may optionally be used as a "generic" class (e.g. |
| List<String>). |
| The actual concrete class that the other side will receive |
| will always be an ArrayList, although the method will be generated |
| to use the List interface. </li> |
| <li><strong>Map</strong> - All elements in the Map must be of one of the |
| types in this list, including other AIDL-generated interfaces and |
| parcelables. Generic maps, (e.g. of the form Map<String,Integer> |
| are not supported. |
| The actual concrete class that the other side will receive |
| will always be a HashMap, although the method will be generated |
| to use the Map interface.</li> |
| <li><strong>CharSequence</strong> - This is useful for the CharSequence |
| types used by {@link android.widget.TextView TextView} and other |
| widget objects. </li> |
| </ul> |
| </li> |
| <li>Other AIDL-generated interfaces, which are always passed by reference. |
| An <code>import</code> statement is always needed for these.</li> |
| <li>Custom classes that implement the <a href="#parcelable">Parcelable |
| protocol</a> and are passed by value. |
| An <code>import</code> statement is always needed for these.</li> |
| </ul> |
| <p>Here is the basic AIDL syntax:</p> |
| <pre>// My AIDL file, named <em>SomeClass</em>.aidl |
| // Note that standard comment syntax is respected. |
| // Comments before the import or package statements are not bubbled up |
| // to the generated interface, but comments above interface/method/field |
| // declarations are added to the generated interface. |
| |
| // Include your fully-qualified package statement. |
| package com.android.sample; |
| |
| // See the list above for which classes need |
| // import statements (hint--most of them) |
| import com.android.sample.IAtmService; |
| |
| // Declare the interface. |
| interface IBankAccountService { |
| |
| // Methods can take 0 or more parameters, and |
| // return a value or void. |
| int getAccountBalance(); |
| void setOwnerNames(in List<String> names); |
| |
| // Methods can even take other AIDL-defined parameters. |
| BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService); |
| |
| // All non-Java primitive parameters (e.g., int, bool, etc) require |
| // a directional tag indicating which way the data will go. Available |
| // values are in, out, inout. (Primitives are in by default, and cannot be otherwise). |
| // Limit the direction to what is truly needed, because marshalling parameters |
| // is expensive. |
| int getCustomerList(in String branch, out String[] customerList); |
| }</pre> |
| |
| <h3 id="implementtheinterface">Implementing the Interface</h3> |
| <p>AIDL generates an interface file for you with the same name as your .aidl |
| file. If you are using the Eclipse plugin, AIDL will automatically be run as part of |
| the build process (you don't need to run AIDL first and then build your project). |
| If you are not using the plugin, you should run AIDL first. </p> |
| <p>The generated interface |
| includes an abstract inner class named Stub that declares all the methods |
| that you declared in your .aidl file. Stub also defines a few helper methods, |
| most notably asInterface(), which takes an IBinder (passed to a client's onServiceConnected() |
| implementation when applicationContext.bindService() succeeds), and returns an |
| instance of the interface used to call the IPC methods. See the section |
| <a href="#calling">Calling an IPC Method</a> for more details on how to make this cast.</p> |
| <p>To implement your interface, extend <em>YourInterface</em>.Stub, |
| and implement the methods. (You can create the .aidl file and implement the stub |
| methods without building between--the Android build process will process .aidl |
| files before .java files.) </p> |
| <p>Here is an example of implementing an interface called IRemoteService, which exposes |
| a single method, getPid(), using an anonymous instance:</p> |
| <pre>// No need to import IRemoteService if it's in the same project. |
| private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){ |
| public int getPid(){ |
| return Process.myPid(); |
| } |
| }</pre> |
| <p>A few rules about implementing your interface: </p> |
| <ul> |
| <li>No exceptions that you throw will be sent back to the caller.</li> |
| <li>IPC calls are synchronous. If you know that an IPC service takes more than |
| a few milliseconds to complete, you should not call it in the Activity/View thread, |
| because it might hang the application (Android might display an "Application |
| is Not Responding" dialog). |
| Try to call them in a separate thread. </li> |
| <li>Only methods are supported; you cannot declare static fields in an AIDL interface.</li> |
| </ul> |
| |
| <h3 id="exposingtheinterface">Exposing Your Interface to Clients</h3> |
| <p>Now that you've got your interface implementation, you need to expose it to clients. |
| This is known as "publishing your service." To publish a service, |
| inherit {@link android.app.Service Service} and implement {@link android.app.Service#onBind |
| Service.onBind(Intent)} to return an instance of the class that implements your interface. |
| Here's a code snippet of a service that exposes the IRemoteService |
| interface to clients. </p> |
| <pre>public class RemoteService extends Service { |
| ... |
| {@include development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java |
| exposing_a_service} |
| }</pre> |
| |
| |
| <h3 id="parcelable">Pass by value Parameters using Parcelables</h3> |
| |
| <p>If you have a class that you would like to send from one process to another through |
| an AIDL interface, you can do that. You must ensure that the code for your class is available |
| to the other side of the IPC. Generally, that means that you're talking to a service that you |
| started.</p> |
| <p>There are five parts to making a class support the Parcelable protocol:</b> |
| <ol> |
| <li>Make your class implement the {@link android.os.Parcelable} interface.</li> |
| <li>Implement the method <code>public void writeToParcel(Parcel out)</code> that takes the |
| current state of the object and writes it to a parcel.</li> |
| <li>Implement the method <code>public void readFromParcel(Parcel in)</code> that reads the |
| value in a parcel into your object.</li> |
| <li>Add a static field called <code>CREATOR</code> to your class which is an object implementing |
| the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.</li> |
| <li>Last but not least, create an aidl file |
| that declares your parcelable class (as shown below). If you are using a custom build process, |
| do not add the aidl file to your build. Similar to a header file in C, the aidl file isn't |
| compiled.</li> |
| </ol> |
| |
| <p>AIDL will use these methods and fields in the code it generates to marshall and unmarshall |
| your objects.</p> |
| <p>Here is an example of how the {@link android.graphics.Rect} class implements the |
| Parcelable protocol.</p> |
| |
| <pre class="prettyprint"> |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| |
| public final class Rect implements Parcelable { |
| public int left; |
| public int top; |
| public int right; |
| public int bottom; |
| |
| public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect>() { |
| public Rect createFromParcel(Parcel in) { |
| return new Rect(in); |
| } |
| |
| public Rect[] newArray(int size) { |
| return new Rect[size]; |
| } |
| }; |
| |
| public Rect() { |
| } |
| |
| private Rect(Parcel in) { |
| readFromParcel(in); |
| } |
| |
| public void writeToParcel(Parcel out) { |
| out.writeInt(left); |
| out.writeInt(top); |
| out.writeInt(right); |
| out.writeInt(bottom); |
| } |
| |
| public void readFromParcel(Parcel in) { |
| left = in.readInt(); |
| top = in.readInt(); |
| right = in.readInt(); |
| bottom = in.readInt(); |
| } |
| } |
| </pre> |
| |
| <p>Here is Rect.aidl for this example</p> |
| |
| <pre class="prettyprint"> |
| package android.graphics; |
| |
| // Declare Rect so AIDL can find it and knows that it implements |
| // the parcelable protocol. |
| parcelable Rect; |
| </pre> |
| |
| <p>The marshalling in the Rect class is pretty simple. Take a look at the other |
| methods on {@link android.os.Parcel} to see the other kinds of values you can write |
| to a Parcel.</p> |
| |
| <p class="warning"><b>Warning:</b> Don't forget the security implications of receiving data from |
| other processes. In this case, the rect will read four numbers from the parcel, |
| but it is up to you to ensure that these are within the acceptable range of |
| values for whatever the caller is trying to do. See |
| <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> for more |
| on how to keep your application secure from malware.</p> |
| |
| <h2 id="calling">Calling an IPC Method</h2> |
| <p>Here are the steps a calling class should make to call your remote interface: </p> |
| <ol> |
| <li>Declare a variable of the interface type that your .aidl file defined. </li> |
| <li>Implement {@link android.content.ServiceConnection ServiceConnection}. </li> |
| <li>Call {@link android.content.Context#bindService(android.content.Intent,android.content.ServiceConnection,int) |
| Context.bindService()}, passing in your ServiceConnection implementation. </li> |
| <li>In your implementation of {@link android.content.ServiceConnection#onServiceConnected(android.content.ComponentName,android.os.IBinder) |
| ServiceConnection.onServiceConnected()}, you will receive an {@link android.os.IBinder |
| IBinder} instance (called <em>service</em>). Call <code><em>YourInterfaceName</em>.Stub.asInterface((IBinder)<em>service</em>)</code> to |
| cast the returned parameter to <em>YourInterface</em> type.</li> |
| <li>Call the methods that you defined on your interface. You should always trap |
| {@link android.os.DeadObjectException} exceptions, which are thrown when |
| the connection has broken; this will be the only exception thrown by remote |
| methods.</li> |
| <li>To disconnect, call {@link android.content.Context#unbindService(android.content.ServiceConnection) |
| Context.unbindService()} with the instance of your interface. </li> |
| </ol> |
| <p>A few comments on calling an IPC service:</p> |
| <ul> |
| <li>Objects are reference counted across processes. </li> |
| <li>You can send anonymous objects |
| as method arguments. </li> |
| </ul> |
| <p>Here is some sample code demonstrating calling an AIDL-created service, taken |
| from the Remote Activity sample in the ApiDemos project.</p> |
| <p>{@sample development/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java |
| exposing_a_service}</p> |
| |
| |
| |