Correcting an AnDevCon Presentation
Here are some clarifications on some points of contention from a presentation I just attended at AnDevCon.
The presenter stated that developers always should use
android:process when writing services. The rationale
— not included in the presentation but elaborated
upon in post-presentation discussion — appears to be based upon
this paragraph from the
Android developer documentation:
In addition, a process’s ranking might be increased because other processes are dependent on it—a process that is serving another process can never be ranked lower than the process it is serving. For example, if a content provider in process A is serving a client in process B, or if a service in process A is bound to a component in process B, process A is always considered at least as important as process B.
The presenter’s argument, therefore, is that a service needs to go in its own process, so that activities that have been moved to the background do not drag down the priority of the process, causing it to be terminated prematurely.
This, however, runs counter to the preceding paragraph:
Android ranks a process at the highest level it can, based upon the importance of the components currently active in the process. For example, if a process hosts a service and a visible activity, the process is ranked as a visible process, not a service process.
and the subsequent paragraph:
Because a process running a service is ranked higher than a process with background activities, an activity that initiates a long-running operation might do well to start a service for that operation, rather than simply create a worker thread—particularly if the operation will likely outlast the activity. For example, an activity that’s uploading a picture to a web site should start a service to perform the upload so that the upload can continue in the background even if the user leaves the activity. Using a service guarantees that the operation will have at least “service process” priority, regardless of what happens to the activity. This is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread.
Hence, background activities will not cause a service process to somehow fall in priority, so there is no reason to fork another service just to help keep the service’s process priority higher.
Furthermore, core Android team members have stated
that developers typically have no need to use
It ties up another VM’s worth of RAM for little added value.
The presenter suggested that developers use a particular
Intent broadcast by the Android Market app (
to get control when their app is installed.
When I pointed out that this is not part of the Android SDK, he indicated that “that’s why it’s cool” and suggested that Google staff told his employer it was OK to use.
IMHO, “that’s why it’s cool” is not a valid justification for
advising people to use code that core Android team members
have indicated will cause their apps to break in the future.
com.android is not part of the Android SDK
and is subject to change without warning.
This isn’t completely the presenter’s fault — I have
seen this broadcast suggested by, of all people, the
Google Analytics folk. I do wish that Google would keep their
story straight internally. For the moment, I am sticking by
the “this broadcast is not part of the SDK” argument, as it remains
consistent with Google’s position regarding other
things people try to use.
Polling by Handler
The presenter showed a code sample demonstrating a service
that implemented an internal polling mechansism using a
postDelayed(). This suggestion, while not
inconceivable, does come with some caveats that the presenter
perhaps did not have time to cover:
The work being done via the
postDelayedwill be performed on the main application thread. That’s possibly still safe for within a service, but services typically are involved in more complex processing that would take too long to perform safely on the main application thread.
This model encourages the creation of “everlasting services”, particularly of the variety that just ties up RAM all day watching the clock tick.
A better solution for most cases — covered later in the presentation
AlarmManager, so the “watch the clock tick”
portion is handled by the operating system, so the service
can get out of RAM (the presenter’s “short-lived services”)
There may be scenarios where polling-by-
appropriate for a service (e.g., polling frequency too
AlarmManager to be practical), but I strongly
suspect they are outliers, not the norm.
The presenter illustrated binding to a service via AIDL. This, of course, is a perfectly valid technique… for certain situations. The problem lies in the presenter’s depiction of using this for services within your application.
This is perhaps an outgrowth of the
outlined above. In that case, you would need the complexity of AIDL, which is designed for inter-process
communication. However, services local to an app should
be in the same process as the activities and the rest of the
app. In that case, the local binding pattern (having the
onBind() method return an instance of a developer-defined
Binder) is typically simpler.
AIDL, however, is very appropriate for exposing a service API to third-party applications, a point which I believe the presenter did mention.
BroadcastReceiver and Device Wakeup
An audience member asked what causes the Android device to
wake up, besides
AlarmManager. What will wake up the device, we have been told, include:
- Incoming phone calls
- Incoming text messages
- Incoming packets on an established socket over a mobile data connection (e.g., 3G)
The latter is used by C2DM, which the presenter did a nice job of introducing.
I am not aware of anything else that will wake up the device, beyond the user pressing the power button.
Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!