Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if an Activity is enabled?

Tags:

Background

I'm trying to check if an activity (or any other app component type, for that matter) is enabled/disabled at runtime.

The problem

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".

The question

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?

like image 546
android developer Avatar asked Nov 16 '14 11:11

android developer


People also ask

How do I know if my android activity is recreated?

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. } }


2 Answers

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

like image 111
Jared Rummler Avatar answered Sep 19 '22 19:09

Jared Rummler


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;
      }
  }
}
like image 29
BamsBamx Avatar answered Sep 17 '22 19:09

BamsBamx