Click here to download the example program.
This is a version of the good old DualService presented in this blog entry. The main difference that the AIDL file has been removed and instead you will find this strange construct in DualService.java:
public class DualServiceBinder extends Binder implements ICounterService {
public int getCounterValue() {
return counter;
}
}
and in onBind:
public IBinder onBind( Intent intent ) {
return dualServiceBinder;
}
Now this DualServiceBinder "Binder derivative" is a strange thing. Binders are serialization-deserialization constructs that turn RPC invocations into byte streams and back. That byte stream can be sent through the Binder kernel driver and that's how interprocess communication works in Android. Binder derivatives are normally generated by the aidl tool. You can do it by hand but it is not for the faint of heart. Basically you have to implement transact/onTransact methods and serialize/deserialize your data by hand. If you follow my advice, you leave it to the aidl tool.
DualServiceBinder does none of it. It implements a plain Java interface (ICounterService) and exposes a plain Java method. On the other side, in DualServiceClient it justs casts the IBinder to ICounterService in the onServiceConnected method and invokes the method on it.
As you might have guessed, this is a hack. The author sidestepped entirely the Android IPC mechanism and abused two properties of the Android application model.
- By default, the Android application manager loads activities/services/providers into the Dalvik VM running in the same Linux process.
- Classes from the same DEX file (there is one DEX file per APK) are loaded by the same class loader.
Do you think I found the hack in a shady, unsupported freeware? No, I found it in a book (actually, my attention was turned to this book by a fellow Android programmer). The book proposes another trick: the "service interface" of their Binder descendant exposes just a getService() method that returns a reference to the Service instance and later the Activity invokes public methods of the service directly, circumventing even their own tricky service interface.
I definitely think it is a bad idea to propagate this hack even though it works on the existing Android implementations and is somewhat faster than the regular, AIDL-based invocation.