Implementing IPC Using AIDL

Follow these steps to implement an IPC service using AIDL.

1. Create your .aidl file - This file defines an interface (YourInterface.aidl) that defines the methods and fields available to a client.

2. 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.

3. 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.

4. Expose your interface to clients - If you're writing a service, you should extend Service and override Service.onBind(Intent) to return an instance of your class that implements your interface.

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:

• Primitive Java programming language types (int, boolean, etc) — No import statement is needed.

• One of the following classes (no import statements needed): o String o List - 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.

o Map - 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.

o CharSequence - This is useful for the CharSequence types used by TextView and other widget objects.

• Other AIDL-generated interfaces, which are always passed by reference. An import statement is always needed for these.

• Custom classes that implement the Parcelable protocol and are passed by value. An import statement is always needed for these. 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;

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

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 Yourlnterface.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(){ public int getPid(){

A few rules about implementing your interface:

• No exceptions that you throw will be sent back to the caller.

• 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.

• Only methods are supported; you cannot declare static fields in an 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 Service and implementService.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 { @Override public IBinder onBind(Intent intent) { // Select the interface to return. If your service only implements // a single interface, you can just return it here without checking the Intent. if (IRemoteService.class.getName().equals(intent.getAction())) { return mBinder;

if (ISecondary.class.getName().equals(intent.getAction())) { return mSecondaryBinder;

return null;

// The IRemoteInterface is defined through IDL

private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { public void registerCallback(IRemoteServiceCallback cb) { if (cb != null) mCallbacks.register(cb);

public void unregisterCallback(IRemoteServiceCallback cb) { if (cb != null) mCallbacks.unregister(cb);

Pass by value Parameters using Parcelables

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:

1. Make your class implement the Parcelable interface.

2. Implement the method public void writeToParcel(Parcel out) that takes the current state of the object and writes it to a parcel.

3. Implement the method public void readFromParcel(Parcel in) that reads the value in a parcel into your object.

4. Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creator interface.

5. 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.

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

Here is an example of how the Rect class implements the 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;

//A secondary interface to the service.

private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() { public int getPid() {

return Process.myPid();

public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) {

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];

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();

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 methods on Parcel to see the other kinds of values you can write to a Parcel.

l97J

0 0

Responses

  • danait
    How to use maps in aidl android?
    6 years ago
  • Jaakko Knihtil
    How to use Parcelable in AIDL in Android?
    5 years ago
  • karoliina
    How to create files in sdk using aidl?
    1 year ago

Post a comment