Using LocalBroadcastManager in Service to Activity Communications

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).

SNAGHTMLec38c45

Once the Support package is part of your environment, make sure the package is available to your project.

SNAGHTMLec92893

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.

private void speedExceedMessageToActivity() {
    Intent intent = new Intent("speedExceeded");
    sendLocationBroadcast(intent);
}
 
private void sendLocationBroadcast(Intent intent){
    intent.putExtra("currentSpeed", currentSpeed);
    intent.putExtra("latitude", latitude);
    intent.putExtra("longitude", longitude);
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

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.

@Override
public void onCreate(Bundle savedInstanceState) {
 
    super.onCreate(savedInstanceState);
    //  ... code removed for brevity
 
    LocalBroadcastManager.getInstance(this).registerReceiver(
            mMessageReceiver, new IntentFilter("speedExceeded"));
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Double currentSpeed = intent.getDoubleExtra("currentSpeed", 20);
        Double currentLatitude = intent.getDoubleExtra("latitude", 0);
        Double currentLongitude = intent.getDoubleExtra("longitude", 0);
        //  ... react to local broadcast message
    }
};

Wrap Up

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 dmccabe@intertech.com or call 651-288-7100 to enroll in our next class today.

  • me

    Thanks for this post! Very helpful and clear :-)

  • Robert Sherman

    I am very interested in your post. The information in your post is very benefitable for me. Thanks for share this post.
    http://kennethnunez.metroblog.com/

  • mrdevxus

    Thank for this post . It help me very much.

  • loleq

    Nice post! But I have a question, when would I actually want to use IBinder?

  • loleq

    Nice post! But I have a question, when would I actually want to use IBinder?

  • loleq

    Nice post! But I have a question, when would I actually want to use IBinder?

  • JWhite

    loleq – good question regarding IBinder. IBinder provides the means for direct and fast communications between say an Activity and a Service. If you will, providing more performant communications but at the expense of some coupling. The intent messaging mechanism provides communications in a less tightly coupled way but may not be as performant as the direct communications provided by the Binder framework and/or AIDL (Android Interface Definition Language). Here is a link to the documentation and examples of how to use IBinder or AIDL: http://developer.android.com/guide/components/bound-services.html

{Offer-Title}

{Offer-PageContent}
Click Here