Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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));
}
}
like image 697
Teo Inke Avatar asked Apr 20 '15 19:04

Teo Inke


People also ask

Is LocalBroadcastManager deprecated?

localbroadcastmanager has been fully deprecated. There will be no further releases of this library. Developers should replace usages of LocalBroadcastManager with other implementations of the observable pattern. Depending on the use case, suitable options may be LiveData or reactive streams.

Why use LocalBroadcastManager?

LocalBroadcastManager is used to register and send a broadcast of intents to local objects in your process. It has lots of advantages: You broadcasting data will not leave your app. So, if there is some leakage in your app then you need not worry about that.


3 Answers

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?

like image 138
Snild Dolkow Avatar answered Oct 08 '22 12:10

Snild Dolkow


check out if your Service and Activity are run in different process, LocalBroadcastManager can't apply in different process.(you should see it in AndroidManifest.xml file)

like image 45
Michael Avatar answered Oct 08 '22 14:10

Michael


Declaration:

private BroadcastReceiver receiver;

Initialization:

receiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        //todo
    }
};

Registration:

LocalBroadcastManager.getInstance(context).registerReceiver(receiver, new IntentFilter("RECEIVER_FILTER"));

context can be any type of Context, you can use the application context.

Unregister:

LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);

Broadcast:

Intent intent = new Intent("RECEIVER_FILTER");
intent.putExtra("EXTRA", someExtra);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
like image 12
smb Avatar answered Oct 08 '22 12:10

smb