Enable and disable a Broadcast Receiver
Solution 1
Well, what you basically have seems OK. I have the following code in one of my projects:
boolean enabled=prefs.getBoolean(key, false);
int flag=(enabled ?
PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
ComponentName component=new ComponentName(EditPreferences.this, OnBootReceiver.class);
getPackageManager()
.setComponentEnabledSetting(component, flag,
PackageManager.DONT_KILL_APP);
I use this to disable a BOOT_COMPLETED
receiver when I don't have any active alarms that need to be scheduled.
My guess is that your ComponentName
is not set up properly (e.g., your leading .
). Try the constructor that I am using, that takes a Context
and a Class
as parameters.
Solution 2
I think using the PackageManager is over-thinking your situation. You have a BroadcastReceiver that needs to sometimes ignore the broadcasts it's listening for. I can think of two easy ways to go about this:
1) Set a flag that your receiver can check to ignore or accept broadcasts, and don't worry about enabling/disabling it at all.
2) Create the BroadcastReceiver programmatically (can just be an inner class, even), and register and unregister it as you need at given parts of your application.
In general I've found that defining my BroadcastReceivers in code instead of XML has provided a lot more flexibility and is generally easier for me to manage.
Related videos on Youtube
Sven
Updated on May 28, 2020Comments
-
Sven almost 4 years
I try to enable and disable a broadcast receiver by using this PackageManager method:
setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
The broadcast receiver is registered in the manifest. The receiver works fine but when i try to disable it, it still receives the broadcast messages. When i disable the receiver in the manifest by "android:enabled="false"", the receiver does not receive anything but I can not enable it.
I call the method from inside a service.
PackageManager pm = getApplicationContext().getPackageManager(); ComponentName componentName = new ComponentName("com.app", ".broadcast_receivers.OnNetworkChangedReceiver"); pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Android manifest:
<receiver android:name=".broadcast_receivers.OnNetworkChangedReceiver" android:enabled="true"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> </intent-filter> </receiver>
The Receiver
public class OnNetworkChangedReceiver extends BroadcastReceiver { private static final String TAG = "OnNetworkChangedReceiver"; @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "in OnNetworkChanged"); } }
I also called the method from inside an Activity yesterday. I thought it worked but today nothing works anymore. Could it be that there is sometimes a big delay in the intent (android.net.conn.CONNECTIVITY_CHANGE) that I misinterpreted yesterday as disabling the receiver?
Is the approach with the PackageManager the right direction or is there a basic error in the idea?
Thanks a lot, Sven
-
CommonsWare about 13 yearsThere are some types of broadcasts (e.g.,
BOOT_COMPLETED
) that cannot be effectively registered viaregisterReceiver()
. Also, over-reliance onregisterReceiver()
leads you to everlasting services -- services just there to maintain a receiver -- which is bad. Disabling the component is a good idea for efficiency, particularly with popular system broadcasts, likeBOOT_COMPLETED
. -
LeffelMania about 13 yearsVery good points. Programmatic BroadcastReceivers do necessitate responsible registering/unregistering to avoid everlasting services. As always it depends on the situation.
-
Sven about 13 yearsThanks a lot for the fast answer. I used the constructor you used and now it works.
-
Mr_and_Mrs_D about 11 yearsSay I have a Boot Receiver - would it be any worth disabling it just before its
onReceive
returns ? Would it then run on next reboot ? -
CommonsWare about 11 years@Mr_and_Mrs_D: If it is disabled when the device reboots, it will not be invoked.
-
Mr_and_Mrs_D about 11 yearsThank you I found out :( I thought the changes would not persist - how come they do ? Does
setComponentEnabledSetting
write in the manifest ? -
CommonsWare about 11 years@Mr_and_Mrs_D: "I thought the changes would not persist" -- then there would have been no point in your trying to disable the receiver, as the boot would already have happened. "how come they do ?" -- because that is the complete and entire point behind
setComponentEnabledSetting()
. -
Mr_and_Mrs_D about 11 years"then there would have been no point in your trying to disable the receiver, as the boot would already have happened" - would it not remove some overhead ? - Since the receiver will be matched against all implicit intents broadcasted while it is registered [it won't actually respond (its onReceive() wont run) as I test for the action (to avoid malicious explicit intents) and I have the BOOT_COMPLETED filter active - so implicit intents won't match, apart from the BOOT one]
-
CommonsWare about 11 years@Mr_and_Mrs_D: "would it not remove some overhead ?" -- most likely you are causing more overhead by your call, as it involves inter-process communication. "Since the receiver will be matched against all implicit intents broadcasted while it is registered" -- since most of the Googlers working on Android are talented developers, I would imagine that they use advanced data structures like
HashMap
to make these lookups efficient. Moreover, since you cannot determine whether your change actually improves performance, you are wasting your time. -
Andy Dennie over 9 yearsMajor caveat: be aware that enabling or disabling a component with DONT_KILL_APP on API 14 or 15 will wipe out any notifications your app has created. See code.google.com/p/android/issues/detail?id=21635
-
Andy Dennie over 9 yearsclarification: my previous comment applies to "ongoing" notifications.
-
GPack over 7 years@CommonsWare Please, i dont understand clearly what the flag DONT_KILL_APP is useful for. Is not the Receiver's onReceive() already guaranteed to be executed completely (with limit of 10 secs)?
-
CommonsWare over 7 years@GPack: It is a flag for
setComponentEnabledSetting()
that controls whether the process should be terminated when we are toggling whether a component is enabled or not. It has nothing directly to do with anyonReceive()
method. -
AJW almost 6 years@CommonsWare Is there a way to only enable the BroadCastReceiver after a BOOT_COMPLETED event? I would like to enable the Receiver immediately after the device re-boots, re-set alarms from my SQLite database that fire due date Notifications and then disable the BroadCastReceiver. Can I disable the Receiver if the alarms are set up with PendingIntents or do I need to always leave enabled (rendering the first question moot)?
-
CommonsWare almost 6 years@AJW: "Can I disable the Receiver if the alarms are set up with PendingIntents" -- if those
PendingIntents
will be for broadcasts to the receiver, the receiver must be enabled to receive those broadcasts. That receiver does not need to be exported, but it does need to be enabled.