page.title=Android Interface Definition Language (AIDL) @jd:body
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:
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.
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.
To create a bounded service using AIDL, follow these steps:
This file defines the programming interface with method signatures.
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.
Implement a {@link android.app.Service Service} and override {@link android.app.Service#onBind onBind()} to return your implementation of the {@code Stub} class.
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.
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:
All elements in the {@link java.util.List} must be one of the supported data types in this
list or one of the other AIDL-generated interfaces or parcelables you've declared. A {@link
java.util.List} may optionally be used as a "generic" class (for example,
List<String>
).
The actual concrete class that the other side receives is always an {@link
java.util.ArrayList}, although the method is generated to use the {@link
java.util.List} interface.
All elements in the {@link java.util.Map} must be one of the supported data types in this
list or one of the other AIDL-generated interfaces or parcelables you've declared. Generic maps,
(such as those of the form
{@code Map
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:
in
, out
, or inout
(see the example below).
Primitives are in
by default, and cannot be otherwise.
Caution: You should limit the direction to what is truly needed, because marshalling parameters is expensive.
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 Android Studio, the incremental build generates the binder class almost immediately.
If you do not use Android Studio, then the Gradle tool generates the binder class next time you
build your application—you should build your project with gradle assembleDebug
(or gradle assembleRelease
) as soon as you're finished writing the {@code .aidl} file,
so that your code can link against the generated class.
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(); } 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:
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.
If you have a class that you would like to send from one process to another through 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:
CREATOR
to your class which is an object implementing
the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.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 uses these methods and fields in the code it generates to marshall and unmarshall your objects.
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; 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(); } }
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 {@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.
Here are the steps a calling class must take to call a remote interface defined with AIDL:
service
). Call
YourInterfaceName.Stub.asInterface((IBinder)service)
to
cast the returned parameter to YourInterface type.A few comments on calling an IPC service:
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}