Wednesday, February 11, 2009

If you're having a hard time with services under Android...

...I can feel your pain. The SDK documentation is good from a referential point of view, but focuses primarily (as you would expect) on the more superficial aspects of the system. Personally, I'm interested in services, IPC mechanisms, and networking so that means I get to read a bunch of API docs and peruse some of the samples.

Now the Android SDK samples aren't bad; however, they are limited. Let's say you're going to write a GUI application (termed for some reason by Google as an 'Activity') and you're going to write a service (as in daemon/service.) Google gives you an example of doing so, but for some reason decided to include all the manifest data for ALL THE SAMPLES into the same manifest file and as one big project (which has implications under Eclipse - which is presumably the development environment you're working in unless you're a sadist and you probably enjoy the pain I'm describing anyhow...)

Well, real projects for useful applications do NOT clump everything together in a single manifest, and they do NOT clump all the source code into the same project. Separating the two is not difficult; HOWEVER, Google's documentation and everything I could find on the 'net regarding service declarations in application manifests neglects to mention what you need to do when yo uhave one project that will be a client of the service and the other project being the service in question. Now, maybe I'm an idiot, but I spent several hours trying to understand why my client application could not successfully call 'startService' on a perfectly named, installed, and runnable service that was on the emulator. The log kept reporting that the component could not be found (while explicitly listing the component correctly which means it had exactly the right package name.) After beating my head for hours, I finally wised up to the fact that I was making an enormous assumption.

I was ASSuming that Google wasn't doing something funny with the service binding mechanism and that because it used a standard Java packaging nomenclature, surely that meant that my client application could call 'startService' and have the OS identify the package correctly. Boy was I wrong.

Apparently, the 'multi-project' trick with a service is that you must declare the service in the manifest of every client application that you will have use the service - even though the declaration is just supposed to be in the service project's manifest according to the documentation (and you cannot tell from the samples because they're all glommed together.)

So, before I forget this, and so I can google my own frustration when I do forget this:

In your client manifest XML you need to add this inside :

<service name="com.MyPackages.MyService.MyServiceClass">

Please note the full package name usage, which is HIGHLY recommended in case you move projects around or rename things. BTW, if your service is to run in its own process, add
android:process=":remote" to your service tag, otherwise it runs locally which I don't understand the purpose of really.

So, to sum up. If you create a service, you'll have a manifest for that project with a service entry in it, as one would expect. If you create a client that will make use of this service, you'll have to add, oddly, a service entry in the client's manifest as well.

I don't know if this is a bug or not, but it was certainly unclear to me. Hope this helps somebody.

No comments:

Post a Comment