Подтвердить что ты не робот

Как проверить, включено ли действие?

Фон

Я пытаюсь проверить, включено ли действие (или любой другой тип компонента приложения) во время выполнения.

Проблема

Можно использовать следующий код:

    final ComponentName componentName = new ComponentName(context, activityClass);
    final PackageManager pm = context.getPackageManager();
    final int result = pm.getComponentEnabledSetting(componentName);

Но возвращаемый результат, как написано на документации, таков:

Возвращает текущее разрешенное состояние для компонента. Может быть одним из COMPONENT_ENABLED_STATE_ENABLED, COMPONENT_ENABLED_STATE_DISABLED или COMPONENT_ENABLED_STATE_DEFAULT. Последнее означает, что компонент включенное состояние основано на исходной информации в манифесте как найдено в ComponentInfo.

Поэтому он не просто включен/отключен, но также "по умолчанию".

Вопрос

Если возвращается "COMPONENT_ENABLED_STATE_DEFAULT", как узнать, по умолчанию ли он включен или отключен (во время выполнения)?

Причина этого вопроса в том, что код должен работать независимо от того, что люди помещают в манифест (для атрибута "enabled" ).

Возможно ли, возможно, использовать намерения, разрешающие?

4b9b3361

Ответ 1

Если возвращается COMPONENT_ENABLED_STATE_DEFAULT, как узнать, по умолчанию ли он включен или отключен?

Вам нужно будет загрузить все компоненты с помощью PackageManager и проверить включенное состояние для соответствующего ComponentInfo. Следующий код должен работать:

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

Тестирование вышеуказанного кода на моем устройстве:

System.out.println(isComponentEnabled(getPackageManager(),
    "com.android.systemui",
    "com.android.systemui.DessertCaseDream"));

System.out.println(isComponentEnabled(getPackageManager(),
    "com.android.settings",
    "com.android.settings.DevelopmentSettings"));

ложно

True

Ответ 2

Я думаю, что поле ComponentInfo.enabled означает значение, заданное в файле AndroidManifest.xml. Если не указано, значение по умолчанию будет истинным. Итак, в следующем примере:

<receiver android:name=".BroadcastReceiver1"
            android:enabled="false" />

<receiver android:name=".BroadcastReceiver2"
            android:enabled="true" />

<receiver android:name=".BroadcastReceiver3" />

поле enabled будет ложным в BroadcastReceiver1, true в BroadcastReceiver2 и true в BroadcastReceiver3, а pm.getComponentEnabledSetting(componentName) будет возвращено ENABLED или DISABLED, если значение в AndroidManifest будет переопределено или DEFAULT, если не переопределить

Затем, согласно @Jared Rummler, ответьте, если pm.getComponentEnabledSetting(componentName) возвращает PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, фактическое значение будет установлено в поле ComponentInfo.enabled, которое будет таким же, как и в AndroidManifest, тогда как ComponentInfo.isEnabled() будет зависеть по всему состоянию приложения

EDIT: Подводя итог:

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

Ответ 3

Код Джареда Раммлера хорош, и он работает, но принимает статус в манифесте.

Чтобы иметь текущий статус компонента внутри моего приложения, мне нужно было создать "ComponentName" через "Контекст пакета" и "Класс компонента", а не "Имя пакета" и "Имя класса".

У меня BroadcastReceiver был установлен на "enabled = false" в манифесте, после этого я включил его в своем приложении с помощью менеджера пакетов, но коды Jared Rummler всегда возвращают мне "STATE_ENABLED_DEFAULT", а "enabled и isEnabled()" всегда возвращали false, Используя "Контекст пакета" и "Класс компонента", я получаю непосредственно "ENABLED_STATE_DISABLED" и "ENABLED_STATE_ENABLED" без использования кода в части по умолчанию, а также "enabled and isEnabled()" вернуло мне ИСТИНА, если я запустил Сервис с помощью менеджера пакетов.

Надеюсь, это полезно, увидимся

public static void enableDisableComponent(Context pckg, Class componentClass, boolean enable){
ComponentName component = new ComponentName(pckg, componentClass);
if(enable == !checkIfComponentIsEnabled(pckg, componentClass)) {
    pckg.getPackageManager().setComponentEnabledSetting(
        component,
        enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
        PackageManager.DONT_KILL_APP
    );
}

}

public static boolean checkIfComponentIsEnabled(Context pckg, Class componentClass){
            boolean ret = false;
            ComponentName componentName = new ComponentName(pckg, componentClass);
            int componentEnabled = pckg.getPackageManager().getComponentEnabledSetting(componentName);
            switch(componentEnabled){
                case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
                    break;
                case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
                    ret = true;
                    break;
                case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
                default:
                    ret = checkEnabledComponentsInfo(pckg, componentClass);
                    break;
            }
            return ret;
        }


private static boolean checkEnabledComponentsInfo(Context pckg, Class componentClass){
    boolean ret = false;
    try{
        PackageInfo packageInfo = pckg.getPackageManager().getPackageInfo(
            pckg.getPackageName(),
            PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS |
                PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS |
                PackageManager.GET_DISABLED_COMPONENTS
        );
        List<ComponentInfo> componentsInfo = new ArrayList<>();
        if(packageInfo.activities != null && packageInfo.activities.length > 0){
            Collections.addAll(componentsInfo, packageInfo.activities);
        }
        if(packageInfo.services != null && packageInfo.services.length > 0){
            Collections.addAll(componentsInfo, packageInfo.services);
        }
        if(packageInfo.providers != null && packageInfo.providers.length > 0){
            Collections.addAll(componentsInfo, packageInfo.providers);
        }
        if(packageInfo.receivers != null && packageInfo.receivers.length > 0){
            Collections.addAll(componentsInfo, packageInfo.receivers);
        }
        if(componentsInfo.size() > 0){
            for(ComponentInfo info : componentsInfo){
                if(info.name.equals(componentClass.getName())){
                    ret = info.isEnabled();
                    break;
                }
            }
        }
    } catch(PackageManager.NameNotFoundException nnfE){
        onException(nnfE);
    }
    return ret;
}

Ответ 4

Попробуйте это.

public class MainActivity extends Activity {

    static boolean running = false;

    @Override
    public void onStart(){
        super.onStart();
        running = true;
    }

    @Override
    public void onStop(){
        super.onStop();
        running = false;
    }

}