I'm trying to have a common object shared for several services in different packages. Each service must call the same object.
For example, Service A (from APK A) instantiates a custom object and I want that Service B and C (from APK B and C) retrieves the reference of this object and call some method of it.
I found in the Android reference that it should be possible by using Parcel :
Active Objects
An unusual feature of Parcel is the ability to read and write active objects. For these objects the actual contents of the object is not written, rather a special token referencing the object is written. When reading the object back from the Parcel, you do not get a new instance of the object, but rather a handle that operates on the exact same object that was originally written. There are two forms of active objects available.
Binder objects are a core facility of Android's general cross-process communication system. The IBinder interface describes an abstract protocol with a Binder object. Any such interface can be written in to a Parcel, and upon reading you will receive either the original object implementing that interface or a special proxy implementation that communicates calls back to the original object. The methods to use are writeStrongBinder(IBinder), writeStrongInterface(IInterface), readStrongBinder(), writeBinderArray(IBinder[]), readBinderArray(IBinder[]), createBinderArray(), writeBinderList(List), readBinderList(List), createBinderArrayList().
I tried to do this by passing my object (who extends binder) through AIDL but nothing works, I always gets a ClassCastException when I'm trying to retrieve the reference from the method createFromParcel(Parcel in).
An example of my code :
public class CustomObject extends Binder implements Parcelable {
public CustomObject() {
super();
}
public static final Parcelable.Creator<CustomObject> CREATOR = new Parcelable.Creator<CustomObject>() {
public CustomObject createFromParcel(Parcel in) {
IBinder i = in.readStrongBinder();
// HOW TO RETRIEVE THE REFERENCE ??
return null;
}
@Override
public CustomObject[] newArray(int size) {
return null;
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStrongBinder(this);
}
}
Is anyone has already done that ?
Thanks in advance !
Here are two approaches.
ICustomObject.aidl
.In this case you do not need to make the object Parcelable. You probably don't even need to write the above code; just use one AIDL-described type in another. For example add a line like this to the main AIDL for service A:
ICustomObject getCustomObject();
In service A, within the Stub
class you've already got, you'll need to simply return something inheriting from ICustomObject
.
ICustomObject
. Simple! No parcels, no readStrongBinder()
, nothing.If you do the above, the Android toolchain generates Java code which marshalls and unmarshalls the object. You could instead write the code yourself.
ICustomObject myObjectWhichActuallyLivesInAnotherProcess = ICustomObject.Stub.asInterface(parcel.readStrongBinder())
or even
ICustomObject myObjectWhichActuallyLivesInAnotherProcess = (ICustomObject)parcel.readStrongBinder().queryLocalInterface("com.your.custom.object");
However I think your life will be more sane if you make everything aidl.
You'll probably want to create an Android "library project" which has ICustomObject.aidl
within it, such that you can share the resulting classes between the projects which build A, B and C.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With