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));
}
}
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.
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.
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?
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)
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With