diff --git a/docs/html/guide/developing/tools/aidl.jd b/docs/html/guide/developing/tools/aidl.jd index d3da2852bdf36..731aef7e77515 100644 --- a/docs/html/guide/developing/tools/aidl.jd +++ b/docs/html/guide/developing/tools/aidl.jd @@ -1,4 +1,4 @@ -page.title=Designing a Remote Interface Using AIDL +page.title=Android Interface Definition Language (AIDL) @jd:body @@ -6,209 +6,367 @@ page.title=Designing a Remote Interface Using AIDL

In this document

    -
  1. Implementing IPC Using AIDL +
  2. Defining an AIDL Interface
      -
    1. Create an .aidl File
    2. -
    3. Implementing the Interface
    4. -
    5. Exposing Your Interface to Clients
    6. -
    7. Pass by value Parameters using Parcelables
    8. +
    9. Create the .aidl file
    10. +
    11. Implement the interface
    12. +
    13. Expose the interface to clients
  3. -
  4. Calling an IPC Method
  5. +
  6. Passing Objects over IPC
  7. +
  8. Calling an IPC Method
-
- - -

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.

- -

The code to do that marshalling is tedious to write, so we provide the AIDL tool to do it -for you.

- -

AIDL (Android Interface Definition Language) is an IDL -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.

-

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.

- - -

Implementing IPC Using AIDL

-

Follow these steps to implement an IPC service using AIDL.

+

See also

    -
  1. Create your .aidl file - This - file defines an interface (YourInterface.aidl) that defines the - methods and fields available to a client.
  2. -
  3. Add the .aidl file to your makefile - (the ADT Plugin for Eclipse - manages this for you). Android includes the compiler, called - AIDL, in the tools/ directory.
  4. -
  5. Implement your interface methods - - 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 YourInterface.Stub - and implements the methods you declared in your .aidl file.
  6. -
  7. Expose your interface to clients - - 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.
  8. +
  9. Bound Services
-

Create an .aidl File

-

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. However, it - is important to note that you must import all non-built-in types, - even if they are defined in the same package as your interface. - Here are the data types that AIDL can support:

+ + + + +

AIDL (Android Interface Definition Language) is similar to other IDLs you might have +worked with. It allows you to define the programming interface that both +the client and service agree upon in order to communicate with each other using +interprocess communication (IPC). On Android, one process cannot 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 objects across that boundary for you. The code to +do that marshalling is tedious to write, so Android handles it for you with AIDL.

+ +

Note: Using AIDL is necessary only if you allow clients from +different applications to access your service for IPC and want to handle multithreading in your +service. If you do not need to perform concurrent IPC across +different applications, you should create your interface by implementing a +Binder or, if you want to perform IPC, but do not need to handle multithreading, +implement your interface using a Messenger. +Regardless, be sure that you understand Bound Services before +implementing an AIDL.

+ +

Before you begin designing your AIDL interface, be aware that calls to an AIDL interface are +direct function calls. You should not make assumptions about the thread in which the call +occurs. What happens is different depending on whether the call is from a thread in the +local process or a remote process. Specifically:

+ -

Here is the basic AIDL syntax:

-
// My AIDL file, named SomeClass.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;
+

Defining an AIDL Interface

-// 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); +

You must define your AIDL interface in an {@code .aidl} file using the Java +programming language syntax, then save it in the source code (in the {@code src/} directory) of both +the application hosting the service and any other application that binds to the service.

- // 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); -}
+

When you build each application that contains the {@code .aidl} file, the Android SDK tools +generate an {@link android.os.IBinder} interface based on the {@code .aidl} file and save it in +the project's {@code gen/} directory. The service must implement the {@link android.os.IBinder} +interface as appropriate. The client applications can then bind to the service and call methods from +the {@link android.os.IBinder} to perform IPC.

-

Implementing the Interface

-

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.

-

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 - Calling an IPC Method for more details on how to make this cast.

-

To implement your interface, extend YourInterface.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.)

-

Here is an example of implementing an interface called IRemoteService, which exposes - a single method, getPid(), using an anonymous instance:

-
// No need to import IRemoteService if it's in the same project.
-private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
+

To create a bounded service using AIDL, follow these steps:

+
    +
  1. Create the .aidl file +

    This file defines the programming interface with method signatures.

    +
  2. +
  3. Implement the interface +

    The Android SDK tools generate an interface in the Java programming language, based on your +{@code .aidl} file. This interface has an inner abstract class named {@code Stub} that extends +{@link android.os.Binder} and implements methods from your AIDL interface. You must extend the +{@code Stub} class and implement the methods.

    +
  4. +
  5. Expose the interface to clients +

    Implement a {@link android.app.Service Service} and override {@link +android.app.Service#onBind onBind()} to return your implementation of the {@code Stub} +class.

    +
  6. +
+ +

Caution: Any changes that you make to your AIDL interface after +your first release must remain backward compatible in order to avoid breaking other applications +that use your service. That is, because your {@code .aidl} file must be copied to other applications +in order for them to access your service's interface, you must maintain support for the original +interface.

+ + +

1. Create the .aidl file

+ +

AIDL uses a simple syntax that lets you declare an interface with one or more methods that can +take parameters and return values. The parameters and return values can be of any type, even other +AIDL-generated interfaces.

+ +

You must construct the {@code .aidl} file using the Java programming language. Each {@code .aidl} +file must define a single interface and requires only the interface declaration and method +signatures.

+ +

By default, AIDL supports the following data types:

+ + + +

You must include an {@code import} statement for each additional type not listed above, even if +they are defined in the same package as your interface.

+ +

When defining your service interface, be aware that:

+ + +

Here is an example {@code .aidl} file:

+ +
+// IRemoteService.aidl
+package com.example.android;
+
+// Declare any non-default types here with import statements
+
+/** Example service interface */
+interface IRemoteService {
+    /** Request the process ID of this service, to do evil things with it. */
+    int getPid();
+
+    /** Demonstrates some basic types that you can use as parameters
+     * and return values in AIDL.
+     */
+    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
+            double aDouble, String aString);
+}
+
+ +

Simply save your {@code .aidl} file in your project's {@code src/} directory and when you +build your application, the SDK tools generate the {@link android.os.IBinder} interface file in your +project's {@code gen/} directory. The generated file name matches the {@code .aidl} file name, but +with a {@code .java} extension (for example, {@code IRemoteService.aidl} results in {@code +IRemoteService.java}).

+ +

If you use Eclipse, the incremental build generates the binder class almost immediately. If you +do not use Eclipse, then the Ant tool generates the binder class next time you build your +application—you should build your project with ant debug (or ant +release) as soon as you're finished writing the {@code .aidl} file, so that your code can +link against the generated class.

+ + +

2. Implement the interface

+ +

When you build your application, the Android SDK tools generate a {@code .java} interface file +named after your {@code .aidl} file. The generated interface includes a subclass named {@code Stub} +that is an abstract implementation of its parent interface (for example, {@code +YourInterface.Stub}) and declares all the methods from the {@code .aidl} file.

+ +

Note: {@code Stub} also +defines a few helper methods, most notably {@code asInterface()}, which takes an {@link +android.os.IBinder} (usually the one passed to a client's {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method) and +returns an instance of the stub interface. See the section Calling an IPC +Method for more details on how to make this cast.

+ +

To implement the interface generated from the {@code .aidl}, extend the generated {@link +android.os.Binder} interface (for example, {@code YourInterface.Stub}) and implement the methods +inherited from the {@code .aidl} file.

+ +

Here is an example implementation of an interface called {@code IRemoteService} (defined by the +{@code IRemoteService.aidl} example, above) using an anonymous instance:

+ +
+private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
     public int getPid(){
         return Process.myPid();
     }
-}
-

A few rules about implementing your interface:

+ public void basicTypes(int anInt, long aLong, boolean aBoolean, + float aFloat, double aDouble, String aString) { + // Does nothing + } +}; +
+ +

Now the {@code mBinder} is an instance of the {@code Stub} class (a {@link android.os.Binder}), +which defines the RPC interface for the service. In the next step, this instance is exposed to +clients so they can interact with the service.

+ +

There are a few rules you should be aware of when implementing your AIDL interface:

-

Exposing Your Interface to Clients

-

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.

-
public class RemoteService extends Service {
-...
-{@include development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
-    exposing_a_service}
-}
+ +

3. Expose the interface to clients

+ +

Once you've implemented the interface for your service, you need to expose it to +clients so they can bind to it. To expose the interface +for your service, extend {@link android.app.Service Service} and implement {@link +android.app.Service#onBind onBind()} to return an instance of your class that implements +the generated {@code Stub} (as discussed in the previous section). Here's an example +service that exposes the {@code IRemoteService} example interface to clients.

+ +
+public class RemoteService extends Service {
+    @Override
+    public void onCreate() {
+        super.onCreate();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        // Return the interface
+        return mBinder;
+    }
+
+    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+        public int getPid(){
+            return Process.myPid();
+        }
+        public void basicTypes(int anInt, long aLong, boolean aBoolean,
+            float aFloat, double aDouble, String aString) {
+            // Does nothing
+        }
+    };
+}
+
+ +

Now, when a client (such as an activity) calls {@link android.content.Context#bindService +bindService()} to connect to this service, the client's {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback receives the +{@code mBinder} instance returned by the service's {@link android.app.Service#onBind onBind()} +method.

+ +

The client must also have access to the interface class, so if the client and service are in +separate applications, then the client's application must have a copy of the {@code .aidl} file +in its {@code src/} directory (which generates the {@code android.os.Binder} +interface—providing the client access to the AIDL methods).

+ +

When the client receives the {@link android.os.IBinder} in the {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback, it must call +YourServiceInterface.Stub.asInterface(service) to cast the returned +parameter to YourServiceInterface type. For example:

+ +
+IRemoteService mIRemoteService;
+private ServiceConnection mConnection = new ServiceConnection() {
+    // Called when the connection with the service is established
+    public void onServiceConnected(ComponentName className, IBinder service) {
+        // Following the example above for an AIDL interface,
+        // this gets an instance of the IRemoteInterface, which we can use to call on the service
+        mIRemoteService = IRemoteService.Stub.asInterface(service);
+    }
+
+    // Called when the connection with the service disconnects unexpectedly
+    public void onServiceDisconnected(ComponentName className) {
+        Log.e(TAG, "Service has unexpectedly disconnected");
+        mIRemoteService = null;
+    }
+};
+
+ +

For more sample code, see the {@code +RemoteService.java} class in ApiDemos.

-

Pass by value Parameters using Parcelables

+ + + + + + +

Passing Objects over IPC

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.

-

There are five parts to making a class support the Parcelable protocol: +an IPC interface, you can do that. However, you must ensure that the code for your class is +available to the other side of the IPC channel and your class must support the {@link +android.os.Parcelable} interface. Supporting the {@link android.os.Parcelable} interface is +important because it allows the Android system to decompose objects into primitives that can be +marshalled across processes.

+ +

To create a class that supports the {@link android.os.Parcelable} protocol, you must do the +following:

  1. Make your class implement the {@link android.os.Parcelable} interface.
  2. -
  3. Implement the method public void writeToParcel(Parcel out) that takes the -current state of the object and writes it to a parcel.
  4. -value in a parcel into your object. +
  5. Implement {@link android.os.Parcelable#writeToParcel writeToParcel}, which takes the +current state of the object and writes it to a {@link android.os.Parcel}.
  6. Add a static field called CREATOR to your class which is an object implementing the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.
  7. -
  8. 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.
  9. +
  10. Finally, create an {@code .aidl} file that declares your parcelable class (as shown for the +{@code Rect.aidl} file, below). +

    If you are using a custom build process, do not add the {@code .aidl} file to your +build. Similar to a header file in the C language, this {@code .aidl} file isn't compiled.

-

AIDL will use these methods and fields in the code it generates to marshall and unmarshall +

AIDL uses these methods and fields in the code it generates to marshall and unmarshall your objects.

-

Here is an example of how the {@link android.graphics.Rect} class implements the -Parcelable protocol.

-
+

For example, here is a {@code Rect.aidl} file to create a {@code Rect} class that's +parcelable:

+ +
+package android.graphics;
+
+// Declare Rect so AIDL can find it and knows that it implements
+// the parcelable protocol.
+parcelable Rect;
+
+ +

And here is an example of how the {@link android.graphics.Rect} class implements the +{@link android.os.Parcelable} protocol.

+ +
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -218,7 +376,8 @@ public final class Rect implements Parcelable {
     public int right;
     public int bottom;
 
-    public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect>() {
+    public static final Parcelable.Creator<Rect> CREATOR = new
+Parcelable.Creator<Rect>() {
         public Rect createFromParcel(Parcel in) {
             return new Rect(in);
         }
@@ -251,43 +410,42 @@ public final class Rect implements Parcelable {
 }
 
-

Here is Rect.aidl for this example

- -
-package android.graphics;
-
-// Declare Rect so AIDL can find it and knows that it implements
-// the parcelable protocol.
-parcelable Rect;
-
- -

The marshalling in the Rect class is pretty simple. Take a look at the other +

The marshalling in the {@code 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.

-

Warning: 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 -Security and Permissions for more -on how to keep your application secure from malware.

+

Warning: Don't forget the security implications of receiving +data from other processes. In this case, the {@code Rect} reads four numbers from the {@link +android.os.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 Security and Permissions for more +information about how to keep your application secure from malware.

-

Calling an IPC Method

-

Here are the steps a calling class should make to call your remote interface:

+ + +

Calling an IPC Method

+ +

Here are the steps a calling class must take to call a remote interface defined with AIDL:

    -
  1. Declare a variable of the interface type that your .aidl file defined.
  2. +
  3. Include the {@code .aidl} file in the project {@code src/} directory.
  4. +
  5. Declare an instance of the {@link android.os.IBinder} interface (generated based on the +AIDL).
  6. Implement {@link android.content.ServiceConnection ServiceConnection}.
  7. -
  8. Call {@link android.content.Context#bindService(android.content.Intent,android.content.ServiceConnection,int) - Context.bindService()}, passing in your ServiceConnection implementation.
  9. -
  10. 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 service). Call YourInterfaceName.Stub.asInterface((IBinder)service) to +
  11. Call {@link +android.content.Context#bindService(android.content.Intent,android.content.ServiceConnection,int) + Context.bindService()}, passing in your {@link +android.content.ServiceConnection} implementation.
  12. +
  13. In your implementation of {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()}, +you will receive an {@link android.os.IBinder} instance (called service). Call +YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.
  14. 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.
  15. -
  16. To disconnect, call {@link android.content.Context#unbindService(android.content.ServiceConnection) +
  17. To disconnect, call {@link +android.content.Context#unbindService(android.content.ServiceConnection) Context.unbindService()} with the instance of your interface.

A few comments on calling an IPC service:

@@ -296,10 +454,12 @@ on how to keep your application secure from malware.

  • You can send anonymous objects as method arguments.
  • + +

    For more information about binding to a service, read the Bound Services +document.

    +

    Here is some sample code demonstrating calling an AIDL-created service, taken from the Remote Service sample in the ApiDemos project.

    {@sample development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java calling_a_service}

    - - - diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 92230a954774c..d81b416709244 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -554,7 +554,6 @@