I am trying to understand how to communicate between applications in Android - not just between Activity
instances.
I set up a 'client' that sends a Messenger obj to a Service (in the Intent
sent to the service); the service creates a Message
obj and sends it back to the 'client' using messenger.send(message)
. This works fine until I try to use the Message.obj to hold an object.
I created my own Parcelable
class MyParcelable
in the service and put it into the message. All works until the message is unmarshalled in the 'client'. The unmarshall fails because the 'client' has no access to the MyParcelable
class. That's obvious - they are in different packages (say com.whatever.myclient
and com.whatever.myserver
). Is this completely the wrong way to go about this?
I have also tried creating a Parcel
and sending that (both applications would thereby have access to the class) - but Parcel
is not Parcelable
. I have read about class loaders being used but do not understand how separate class loaders in separate applications (processes, if I understand Android architecture in that regard). That is, how can one class loader be 'taught' about a class that exists in the other class loader? It certainly seems like there should be an obvious 'this is how you do it' but I have not seen it yet.
You cannot unmarshall a class at a process that has no knowledge of this class (as you already correctly pointed out). If you want
MyParcelable
to be sent to yourService
, then you need to includeMyParcelable
in theService
at build, and include the rightClassLoader
to be used when unmarshalling, because unmarshalling is done by a system thread, which doesn't know whatMyParcelable
is even if you included it at compile time.EDIT:
Make a library of your common classes and include it in both applications (the application and the
Service
). You can either mark it as an Android library (in Eclipse this is right under the project's Android properties) or export it as a JAR and import it in both apps. It's always a good idea to have independent classes in a library instead of putting them in the apps directly. This way you can reuse them on other projects ;)You can get your
ClassLoader
from the current thread when you're executing your code. Obviously thisClassLoader
knows about your classes because it's executing your code ;) For example inActivity#onCreate()
, you can doThread.currentThread.getContextClassLoader()
. Since yourMyParcelable
class is also included on theService
, you can do the same to get a validClassLoader
to unmarshall.Another solution for IPC is to define an AIDL interface so you don't have to implement
Parcelable
.OK, I found the 'easy way' I was looking for. You can put a Bundle into the Message.obj field. Bundle is Parcelable so can be transported between client and server. There's no issue of the server not knowing what class it's receiving as Bundle is 'built into' Android Java. And Bundle can apparently include 'sub-Bundles' with in. This is simpler than having to deal with ensuring both parties know the definition of a user-defined class. Thanks for the answers above - I certainly appreciated the info!
If you dont want to use a persistence layer somewhere ( i use cloud apis ) you could run a service in a separate process and bind to the service the respective apps that need the shared value-holder type object data. the service would be where you construct and get the obj values on behalf of connecting ( binding ) apps.