Search code examples
androidservicebroadcastreceiverbroadcastintentservice

Why would LocalBroadcastManager not work instead of Context.registerReceiver?


I had to implement a feature to this app which consists of an Activity and a Service working on the background (it implements Service, not IntentService).

I went through a few tutorials on the Internet that are supposed to work, and they all use LocalBroadcastManager, which by the way is the recommended by Android:

If you don't need to send broadcasts across applications, consider using this class with LocalBroadcastManager instead of the more general facilities described below.

I literally lost a day to find out the problem why it wouldn't work for me: it only works if I use Context.sendBroadcast(). and Context.registerReceiver() instead of the LocalBroadcastManager methods.

Now my app is working, but I feel I am going against the best practices, and I don't know why. Any ideas why it could be happening?

EDIT:

After I wrote this question I went further on the problem. LocalBroadcastManager works through a Singleton, as we should call LocalBroadcastManager.getInstance(this).method(). I logged both instances (in the Activity and in the Service) and they have different memory addresses. Now I came to another question, shouldn't a Service have the same Context as the Activity that called it? From this article a Service runs on the Main Thread, hence I'd think the Context would be the same.

Any thoughts on that? (sorry for the long post)

Code samples:

MyService

public class MyService extends Service {

...

// When an event is triggered, sends a broadcast

Intent myIntent = new Intent(MainActivity.MY_INTENT);
myIntent.putExtra("myMsg","msg");
sendBroadcast(myIntent);

// Previously I was trying:
// LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(myIntent);

}

MyActivity

public class MainActivity {

...

private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) { 
            Log.d("onReceive", "received!");
            // TODO something
        }
    };

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
    // Previously I was trying:
    // LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
}
}

Solution

  • I've never used LocalBroadcastManager, but it sounds like you have to register your receiver on there (i.e. lbm.registerReceiver(...), not mycontext.registerReceiver(...)). Are you doing that?

    Now I came to another question, shouldn't a Service have the same Context as the Activity that called it? From this article a Service runs on the Main Thread, hence I'd think the Context would be the same.

    The Context class is not related to threads. In fact, both Service and Activity are (indirect) subclasses of Context -- so they're their own Contexts!
    That's why you can use "this" as a Context.

    But regardless of which context you send into LocalBroadcastManager.getInstance(), you should be getting the exact same LBM instance out. I can't think of any reason that you wouldn't -- except if you're running the Activity and Service in different processes?