I'm trying to check if an activity (or any other app component type, for that matter) is enabled/disabled at runtime.
It's possible to use the next code:
final ComponentName componentName = new ComponentName(context, activityClass);
final PackageManager pm = context.getPackageManager();
final int result = pm.getComponentEnabledSetting(componentName);
But the returned result, as written on the documentation is:
Returns the current enabled state for the component. May be one of COMPONENT_ENABLED_STATE_ENABLED, COMPONENT_ENABLED_STATE_DISABLED, or COMPONENT_ENABLED_STATE_DEFAULT. The last one means the component's enabled state is based on the original information in the manifest as found in ComponentInfo.
So it's not just enabled/disabled, but also "default".
If "COMPONENT_ENABLED_STATE_DEFAULT" is returned, how do I know if it's default as enabled or disabled (at runtime)?
The reason for this question is that the code should work no matter what people put in the manifest (for the "enabled" attribute) .
Is it possible perhaps to use intents resolving?
You can determine if the activity is finishing by user choice (user chooses to exit by pressing back for example) using isFinishing() in onDestroy . @Override protected void onDestroy() { super. onDestroy(); if (isFinishing()) { // wrap stuff up } else { //It's an orientation change. } }
If
COMPONENT_ENABLED_STATE_DEFAULT
is returned, how do I know if it's default as enabled or disabled?
You will need to load all the components using PackageManager and check the enabled state for the matching ComponentInfo. The following code should work:
public static boolean isComponentEnabled(PackageManager pm, String pkgName, String clsName) {
ComponentName componentName = new ComponentName(pkgName, clsName);
int componentEnabledSetting = pm.getComponentEnabledSetting(componentName);
switch (componentEnabledSetting) {
case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
return false;
case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
return true;
case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
default:
// We need to get the application info to get the component's default state
try {
PackageInfo packageInfo = pm.getPackageInfo(pkgName, PackageManager.GET_ACTIVITIES
| PackageManager.GET_RECEIVERS
| PackageManager.GET_SERVICES
| PackageManager.GET_PROVIDERS
| PackageManager.GET_DISABLED_COMPONENTS);
List<ComponentInfo> components = new ArrayList<>();
if (packageInfo.activities != null) Collections.addAll(components, packageInfo.activities);
if (packageInfo.services != null) Collections.addAll(components, packageInfo.services);
if (packageInfo.providers != null) Collections.addAll(components, packageInfo.providers);
for (ComponentInfo componentInfo : components) {
if (componentInfo.name.equals(clsName)) {
return componentInfo.isEnabled();
}
}
// the component is not declared in the AndroidManifest
return false;
} catch (PackageManager.NameNotFoundException e) {
// the package isn't installed on the device
return false;
}
}
}
Testing the above code on my device:
System.out.println(isComponentEnabled(getPackageManager(),
"com.android.systemui",
"com.android.systemui.DessertCaseDream"));
System.out.println(isComponentEnabled(getPackageManager(),
"com.android.settings",
"com.android.settings.DevelopmentSettings"));
false
true
I think the field ComponentInfo.enabled
means the value set in the AndroidManifest.xml file. If not specified, the default will be true. So, in the following example:
<receiver android:name=".BroadcastReceiver1"
android:enabled="false" />
<receiver android:name=".BroadcastReceiver2"
android:enabled="true" />
<receiver android:name=".BroadcastReceiver3" />
the enabled
field will be false in BroadcastReceiver1, true in BroadcastReceiver2 and true in BroadcastReceiver3, while pm.getComponentEnabledSetting(componentName)
will return ENABLED or DISABLED if the value in AndroidManifest is overridden or DEFAULT if not overriden
Then, according to @Jared Rummler answer if pm.getComponentEnabledSetting(componentName)
returns PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
the actual value will be the one set in ComponentInfo.enabled
field which will be the same as the one set in AndroidManifest, while ComponentInfo.isEnabled()
would depend on the whole application state
EDIT: To sum up:
public static boolean isComponentEnabled(PackageManager pm, String pkgName, String clsName) {
ComponentName componentName = new ComponentName(pkgName, clsName);
int componentEnabledSetting = pm.getComponentEnabledSetting(componentName);
switch (componentEnabledSetting) {
case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
return false;
case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
return true;
case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
default:
// We need to get the application info to get the component's default state
try {
PackageInfo packageInfo = pm.getPackageInfo(pkgName, PackageManager.GET_ACTIVITIES
| PackageManager.GET_RECEIVERS
| PackageManager.GET_SERVICES
| PackageManager.GET_PROVIDERS
| PackageManager.GET_DISABLED_COMPONENTS);
List<ComponentInfo> components = new ArrayList<>();
if (packageInfo.activities != null) Collections.addAll(components, packageInfo.activities);
if (packageInfo.services != null) Collections.addAll(components, packageInfo.services);
if (packageInfo.providers != null) Collections.addAll(components, packageInfo.providers);
for (ComponentInfo componentInfo : components) {
if (componentInfo.name.equals(clsName)) {
return componentInfo.enabled; //This is the default value (set in AndroidManifest.xml)
//return componentInfo.isEnabled(); //Whole package dependant
}
}
// the component is not declared in the AndroidManifest
return false;
} catch (PackageManager.NameNotFoundException e) {
// the package isn't installed on the device
return false;
}
}
}
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