43
votes

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

2
By the way @Sven, your initial mistake was a very common one. Your ComponentName needed ("com.app", "com.app.broadcast_receivers.OnNetworkChangedReceiver"); I realize this solution looks weird, because the package name seems to be listed twice. And since the 'New Android Wizard...' may only ask you for only one package name when you first create a project, it's easy to think there is only one, but under the covers it actually takes that string you give it and assigns to two different package names, both the Application package name and also the Activity package name. - Stephan Branczyk
Using 0 instead of PackageManager.DONT_KILL_APP could also help you get rid of the activity, if I'm reading the docs correctly: developer.android.com/reference/android/content/pm/… in the SetComponentEnabledSetting section. - Ehtesh Choudhury

2 Answers

74
votes

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.

3
votes

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.