In Android, there are ways to have Activities start other Activities, Activities start Services, Services start Services, and Services to start Activities. In actuality, these are indirect actions accomplished via Intent messaging through Android. You create an Intent object providing explicit or implicit details about the Activity or Service you want started and then request startActivity( ) or startService( ) with the Intent passed as a parameter. Android is responsible for actually starting the Activity or Service given your message.
Service to Activity Communication Options
Communication between running instances of Service and Activity are sometimes a bit harder to accomplish. Services are often accomplishing work behind the scenes. When the work creates information needed to inform the Activity (possibly in order to update the UI), how do you have the Service signal the Activity with that information? Options include:
Using the IBinder object is some sort of cross Service-to-Activity communications. As the documentation for IBinder indicates, its purpose is to be “the core part of a lightweight remote procedure call mechanism designed for high performance when performing in-process and cross-process calls.” This can be a bit overwhelming and complicated when all you want to do is pass some simple data between components (Service and Activity) and you don’t really want to make a remote procedure call.
Use a notification status bar message with a PendingIntent that can message the Activity. This is extremely helpful when the user should be involved in the communication between the Service and Activity. For example, when a new email arrives, it is usually via status bar message that a background service checking for new email detects an incoming email and posts a status bar message to alert the user to open the email Activity. However, this can be a less than an optimal solution where the Service-to-Activity communication is suppose to be quietly accomplished with no user interaction. As the documentation says, “A status bar notification should be used for any case in which a background service needs to alert the user about an event that requires a response. A background service should never launch an activity on its own in order to receive user interaction.”
A service could launch its own Broadcast Intent and an Activity could be setup as a Broadcast receiver. However, the broadcast message system in Android is, per the documentation, really meant for sending broadcasts across applications and should not be used for local (inside app component to app component) communications. There are performance/efficiency and security issues with broadcasts receivers, particularly when the broadcast is sticky (read the documentation and see here).
LocalBroadcastManager – a preferred option?
As a preferred alternate consider using the LocalBroadcastManager to send a local broadcast message from the Service to the Activity (or between any app components for that matter). Per the documentation, a local broadcast message has two key advantages over using a Broadcast Intent (a.k.a. global broadcast message). Namely, the data doesn’t leave the application and it is more efficient. Plus, I think you’ll find the API more easy to use than IBinder and the communications more direct and not requiring user action like the notification status bar.
Using LocalBroadcastManager – Where to Get It
The LocalBroadcastManager used to send local broadcast messages is not part of the “normal” Android API. It is part of the Android Support package. In order to add the Android Support package to your Android application environment, open the Android SDK Manager, find the “Extras” folder and select Android Support package for installation (as shown below).
Once the Support package is part of your environment, make sure the package is available to your project.
LocalBroadcastManager Sending an Intent to an Activity
With the appropriate library in place, you can use the android.support.v4.content.LocalBroadcastManager class to send an local broadcast message. Below are some example methods from a speed and location background Service that create an Intent communicating that the speed of the device has been determined to exceed some limit. The Service uses the LocalBroadcastManager to send a local broadcast message to inform an Activity of this excessive speed. It really is just as easy as creating an Intent object and calling sendBroadcast( ) using that Intent object.
Listening for a Local Broadcast Message
On the Activity side (or for that matter any local application component could also listen for the local message), register for the local broadcast message of interest – in this case the “speedExceeded” broadcast message. I chose to register for the broadcast in the onCreate( ) method of my Activity.
That’s all there is to using a local broadcast message to allow your Service to communicate with an Activity or other component in your Android application. Interested in learning more about Android? Contact Dan McCabe at email@example.com or call 651-288-7100 to enroll in our next class today.