Как проверить, включено ли действие?
Фон
Я пытаюсь проверить, включено ли действие (или любой другой тип компонента приложения) во время выполнения.
Проблема
Можно использовать следующий код:
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" ).
Возможно ли, возможно, использовать намерения, разрешающие?
Ответы
Ответ 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;
}
}