I have an activity in package A (SignerClient), and a service in package B (MyService)
The activity’s resultreceiver:
private ResultReceiver resultreceiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
...
}
};
Starting the service:
Intent intent = new Intent("com.example.STARTSERVICE");
intent.putExtra("resultreceiver", resultreceiver);
startService(intent);
Receiving end:
ResultReceiver rr = (ResultReceiver) intent.getParcelableExtra("resultreceiver");
Doing this when client and server are in the same package works fine. But in this case i get:
FATAL EXCEPTION: IntentService[MyService]
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.example.cryptoclient.SignerClient$1
at android.os.Parcel.readParcelable(Parcel.java:1883)
at android.os.Parcel.readValue(Parcel.java:1771)
at android.os.Parcel.readMapInternal(Parcel.java:2008)
at android.os.Bundle.unparcel(Bundle.java:208)
at android.os.Bundle.getParcelable(Bundle.java:1100)
at android.content.Intent.getParcelableExtra(Intent.java:3396)
at org.axades.service.MyService.onHandleIntent(MyService.java:28)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.os.HandlerThread.run(HandlerThread.java:60)
What am I missing? Is my idea even possible?
Yes, your idea is possible. The
ClassNotFoundExceptionexception is thrown because you are trying to unparcel a class that was created in a different process by a differentClassLoader.ResultReceiverclass implementsParcelableinterface which is suitable for inter-process calls (IPC), however to read your object in the service you need to use the same ClassLoader, that was used for object creation in the client application (i.e. in the activity). To get that ClassLoader on the service side, callcreatePackageContextmethod passing client package name andCONTEXT_INCLUDE_CODE|CONTEXT_IGNORE_SECURITYcombination of flags. This will return client Context object from which the correct ClassLoader object can be obtained.Example:
I’ve just used it in my code – works like a charm.
UPDATE
However I suggest to consider using
Messengerinstead ofResultReceiver. It implementsParcelableinterface and does not need to be extended thus the ClassLoader issue isn’t possible. And it’s also recommended in the official documentation.UPDATE 2
In case you still prefer to use
ResultReceivertake a look at Robert’s answer in this thread. It looks cleaner and simpler than hacky context manipulations.