Here's a concrete example of a client using Android Interface Definition language (AIDL) for Inter-Process communication (IPC) with a Service setup in another Android application on the phone.

In the previous article, we described how to set up a remote service using AIDL. Before that, in a first article, we showed an implementation of a custom Parcelable User class to pass across processes. Now, we're going to look at the client and finally produce a little concrete example on the phone. Talking about concepts is all fine and dandy, but as engineers, we need to have some sort of working software in the end. An AIDL Client/Service .zip file will be included at the end of this article for download, so the reader can play around with the code.

Since we need to test access to the service from a different process, we start by creating a separate Android project from our service. We'll need a very basic UI so that we can test our remote service. Therefore, our client must be an Activity. Our client must also be able to:

And we'll implement our ServiceConnection as an inner class of the client Activity:

/** Inner class used to connect to UserDataService */
class DataConnection implements ServiceConnection {
/** is called once the bind succeeds */
public void onServiceConnected(ComponentName name, IBinder service) {
dataService = IUserDataService.Stub.asInterface(service);
}
/*** is called once the remote service is no longer available */
public void onServiceDisconnected(ComponentName name) { //
dataService = null;
}
}

The Stub.asInterface method was one of the automatically generated methods by the AIDL tool when we set up our service. The rest is pretty much self-documenting.

Next, we'll implement a couple of Activity lifecycle methods for the client:

/** Called when the activity is first created */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// connect to the service
conn = new DataConnection();
// name must match the service's Intent filter in the Service Manifest file
Intent intent = new Intent("com.ts.userdata.IUserDataService");
// bind to the Service, create it if it's not already there
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
/** Clean up before Activity is destroyed */
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
dataService = null;
}

Next, we'll create a very basic UI consisting of a field and a submit button. Here are the most relevant parts:

The above implementation is of course hidden to the clients, and is not distributed to anyone outside the service. However, the client needs access to the AIDL files and also the Parcelable User class (more on that later) to be able to use the service. So we need to copy those with their original package structure to the client project. For our demonstration purposes, we'll deploy both applications on the phone at the same time just by deploying the client. The easiest way to do that is to include the service application in the client application's build path (in Eclipse, Go to Project/Properties/Java Build Path/ and add the Service project). Once we do that and deploy, here's what we get on the actual phone:

The IPC worked. We have effectively communicated across processes, i.e. Android applications.

Note that we have to distribute not only the AIDL files, but also our custom Parcelable User class to our clients since they need to get it at the other end of IPC channel. That could be a problem because User is not an interface. If we ever need to change its implementation, we will break our existing clients. A simpler and more stable AIDL service would be one that only uses types provided by the system that are supported out-of-the-box, like our phone lookup service in the previous article, which returned a List of String types. So the final word is, keep those issues in mind when deciding to create your own Parcelable classes in AIDL.