android - programacion - ¿Cómo comprobar si una actividad está habilitada?
programacion android studio pdf (4)
Si se devuelve
COMPONENT_ENABLED_STATE_DEFAULT
, ¿cómo puedo saber si está predeterminado como habilitado o deshabilitado?
Deberá cargar todos los componentes utilizando PackageManager y verificar el estado habilitado para el ComponentInfo correspondiente. El siguiente código debería funcionar:
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;
}
}
}
Probando el código anterior en mi dispositivo:
System.out.println(isComponentEnabled(getPackageManager(),
"com.android.systemui",
"com.android.systemui.DessertCaseDream"));
System.out.println(isComponentEnabled(getPackageManager(),
"com.android.settings",
"com.android.settings.DevelopmentSettings"));
falso
cierto
Fondo
Estoy tratando de verificar si una actividad (o cualquier otro tipo de componente de la aplicación, para el caso) está habilitada / deshabilitada en el tiempo de ejecución.
El problema
Es posible utilizar el siguiente código:
final ComponentName componentName = new ComponentName(context, activityClass);
final PackageManager pm = context.getPackageManager();
final int result = pm.getComponentEnabledSetting(componentName);
Pero el resultado devuelto, tal como está escrito en la documentación es:
Devuelve el estado habilitado actual para el componente. Puede ser uno de COMPONENT_ENABLED_STATE_ENABLED, COMPONENT_ENABLED_STATE_DISABLED, o COMPONENT_ENABLED_STATE_DEFAULT. El último significa que el estado habilitado del componente se basa en la información original en el manifiesto que se encuentra en ComponentInfo.
Así que no solo está habilitado / deshabilitado, sino también "predeterminado".
La pregunta
Si se devuelve "COMPONENT_ENABLED_STATE_DEFAULT", ¿cómo puedo saber si está predeterminado como habilitado o deshabilitado (en tiempo de ejecución)?
El motivo de esta pregunta es que el código debe funcionar sin importar lo que las personas pongan en el manifiesto (para el atributo "habilitado").
¿Es posible tal vez usar intenciones de resolución?
Creo que el campo ComponentInfo.enabled
significa el valor establecido en el archivo AndroidManifest.xml. Si no se especifica, el valor predeterminado será verdadero. Entonces, en el siguiente ejemplo:
<receiver android:name=".BroadcastReceiver1"
android:enabled="false" />
<receiver android:name=".BroadcastReceiver2"
android:enabled="true" />
<receiver android:name=".BroadcastReceiver3" />
el campo enabled
será falso en BroadcastReceiver1 , verdadero en BroadcastReceiver2 y verdadero en BroadcastReceiver3 , mientras que pm.getComponentEnabledSetting(componentName)
devolverá ENABLED o DISABLED si el valor en AndroidManifest está anulado o DEFAULT si no se anula
Luego, de acuerdo con la respuesta de @Jared Rummler si pm.getComponentEnabledSetting(componentName)
devuelve PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
el valor real será el establecido en el campo ComponentInfo.enabled
que será el mismo que el establecido en AndroidManifest, mientras que ComponentInfo.isEnabled()
dependería de todo el estado de la aplicación
EDITAR: Para resumir:
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;
}
}
}
El código de Jared Rummler es bueno y funciona pero toma el estado en el manifiesto.
Para tener el estado actual de un componente dentro de mi aplicación, necesitaba crear el "ComponentName" a través del "Contexto del paquete" y la "Clase del componente" y no el "Nombre del paquete" y el "Nombre de la clase".
Tuve un BroadcastReceiver configurado en "habilitado = falso" en el manifiesto, después de eso lo habilité dentro de mi aplicación usando el administrador de paquetes, pero los códigos de Jared Rummler siempre me devuelven "STATE_ENABLED_DEFAULT" y "habilitado y no puedo mantenerlo ()" siempre devolvió falso . Usando el "Contexto del paquete" y la "Clase de componente" obtengo directamente el "ENABLED_STATE_DISABLED" y "ENABLED_STATE_ENABLED" sin usar el código en la parte predeterminada, también el "habilitado y no está habilitado ()" me devolvió de todos modos FALSO si he comenzado el receptor utilizando el gestor de paquetes.
Espero que esto sea útil, nos vemos
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;
}
Prueba esto.
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;
}
}