summaryrefslogtreecommitdiff
path: root/docs/html/guide/developing/aidl.jd
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/guide/developing/aidl.jd')
-rwxr-xr-xdocs/html/guide/developing/aidl.jd301
1 files changed, 301 insertions, 0 deletions
diff --git a/docs/html/guide/developing/aidl.jd b/docs/html/guide/developing/aidl.jd
new file mode 100755
index 000000000000..145fd93fc47f
--- /dev/null
+++ b/docs/html/guide/developing/aidl.jd
@@ -0,0 +1,301 @@
+page.title=Designing a Remote Interface Using AIDL
+@jd:body
+
+<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>
+<p>This page includes the following main topics: </p>
+<ul>
+ <li><a href="#implementing">Implementing IPC Using AIDL</a></li>
+ <li><a href="#calling">Calling an .aidl (IPC) Class </a></li>
+</ul>
+<h2>Implementing IPC Using AIDL <a name="implementing"></a></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 <a href="{@docRoot}intro/installing.html#developingwitheclipse">Eclipse
+ plugin</a> 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>Create an .aidl File <a name="aidlsyntax"></a></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)
+ &mdash; 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&lt;String&gt;).
+ 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&lt;String,Integer&gt;
+ 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&lt;String&gt; 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>Implementing the Interface <a name="implementtheinterface"></a></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 &quot;Application
+ is Not Responding&quot; 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>Exposing Your Interface to Clients<a name="exposingtheinterface" id="exposingtheinterface"></a></h3>
+<p>Now that you've got your interface implementation, you need to expose it to clients.
+ This is known as &quot;publishing your service.&quot; 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>
+
+<a name="parcelable"></a>
+<h3>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:
+<ul>
+<li>If you are developing with Eclipse/ADT, follow these steps:
+<ol type="a">
+<li>In the Package Explorer view, right-click on the project.</li>
+<li>Choose <strong>Android Tools</strong> > <strong>Create Aidl preprocess file
+for Parcelable classes</strong>.</li>
+<li>This will create a file called "project.aidl" in the root of the project.
+The file will be automatically used when compiling an aidl file that uses the
+parcelable classes.</li>
+</ol>
+</li>
+<li>If you are developing with Ant or are using a custom build process, 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>
+</ul>
+</li>
+</ul>
+<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&lt;Rect&gt; CREATOR = new Parcelable.Creator&lt;Rect&gt;() {
+ 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}devel/security.html">Security and Permissions in Android</a> for more
+on how to keep your application secure from malware.</p>
+
+<h2>Calling an IPC Method <a name="calling"></a></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>
+
+
+