summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/developing/tools/aidl.jd
blob: abfa8b17ad4f8799e17d058e8659acf752c40ae7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
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)
        &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 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 &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 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 &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>


<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>
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&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}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>