Modo de tareas bloqueadas

En esta guía para desarrolladores, se explica cómo se pueden bloquear los dispositivos dedicados a una sola app o a un conjunto de apps. Si eres un desarrollador de administración de movilidad empresarial (EMM) o un integrador de soluciones, lee esta guía para agregar el modo de tareas bloqueadas a tu solución.

Descripción general

Android puede ejecutar tareas con un método de tipo kiosco envolvente que se denomina modo de tareas bloqueadas. Puedes usar el modo de tareas bloqueadas si desarrollas una aplicación de kiosco o un selector para presentar una colección de aplicaciones. Cuando el sistema se ejecuta en este modo, los usuarios del dispositivo no suelen ver las notificaciones, no pueden acceder a apps que no estén incluidas en la lista de entidades permitidas ni volver a la pantalla principal (a menos que la pantalla principal esté incluida en la lista de entidades permitidas).

Solo las apps incluidas en la lista de entidades permitidas por un controlador de política de dispositivo (DPC) pueden ejecutarse cuando el sistema está en modo de tareas bloqueadas. Las apps se incluyen en la lista de entidades permitidas porque la persona que usa el dispositivo no siempre puede salir del modo de tareas bloqueadas.

La forma en que combines la app incluida en la lista de entidades permitidas para el modo de tareas bloqueadas y el DPC de la lista de entidades permitidas dependerá del problema que quieras resolver. Estos son algunos ejemplos:

  • Un solo paquete de app que combina un kiosco (para presentar contenido) y un mini DPC (para incluir en la lista de entidades permitidas para el modo de tareas bloqueadas).
  • Es un DPC que forma parte de una solución de administración de movilidad empresarial, que inicia las apps para dispositivos móviles del cliente en modo de tareas bloqueadas.

Disponibilidad

El sistema se puede ejecutar en modo de tareas bloqueadas en Android 5.0 o versiones posteriores. En la tabla 1, se muestra qué versiones de Android admiten apps para incluir apps en la lista de entidades permitidas por usuario.

Tabla 1: Compatibilidad de la versión de Android con los modos de administrador de DPC
Versión de Android El DPC administra Notas
Android 5.0 (nivel de API 21) o una versión posterior Dispositivo completamente administrado
Android 8.0 (nivel de API 26) o una versión posterior Usuario secundario afiliado El usuario secundario debe estar afiliado al usuario principal. Consulta la descripción general de varios usuarios.
Android 9.0 (nivel de API 28) o una versión posterior Usuario secundario

En Android 9.0 o versiones posteriores, un DPC puede iniciar la actividad de cualquier app en el modo de tareas bloqueadas. En versiones anteriores, la app ya debe admitir el inicio de su propia actividad en el modo de tareas bloqueadas.

Agregar apps a la lista de entidades permitidas

Un DPC debe incluir apps en la lista de entidades permitidas para que puedan usarse en el modo de tareas bloqueadas. Llama a DevicePolicyManager.setLockTaskPackages() a fin de incluir apps en la lista de entidades permitidas para el modo de tareas bloqueadas, como se muestra en el siguiente ejemplo:

Kotlin

// Allowlist two apps.
private val KIOSK_PACKAGE = "com.example.kiosk"
private val PLAYER_PACKAGE = "com.example.player"
private val APP_PACKAGES = arrayOf(KIOSK_PACKAGE, PLAYER_PACKAGE)

// ...

val context = context
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
val adminName = getComponentName(context)
dpm.setLockTaskPackages(adminName, APP_PACKAGES)

Java

// Allowlist two apps.
private static final String KIOSK_PACKAGE = "com.example.kiosk";
private static final String PLAYER_PACKAGE = "com.example.player";
private static final String[] APP_PACKAGES = {KIOSK_PACKAGE, PLAYER_PACKAGE};

// ...

Context context = getContext();
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminName = getComponentName(context);
dpm.setLockTaskPackages(adminName, APP_PACKAGES);

Para descubrir las apps que anteriormente estaban incluidas en la lista de entidades permitidas para el modo de tareas bloqueadas, un DPC puede llamar a DevicePolicyManager.getLockTaskPackages(). Otras apps pueden llamar a DevicePolicyManager.isLockTaskPermitted() para confirmar que un paquete de apps admite el modo de tareas bloqueadas.

Iniciar modo de tareas bloqueadas

En Android 9.0 (nivel de API 28) o versiones posteriores, puedes iniciar la actividad de otra app en el modo de tareas bloqueadas. Si una actividad ya se está ejecutando en primer o segundo plano, debes reiniciarla. Llama a ActivityOptions.setLockTaskEnabled() y proporciona estas opciones cuando inicies la actividad. En el siguiente fragmento, se muestra una forma de hacerlo:

Kotlin

// Set an option to turn on lock task mode when starting the activity.
val options = ActivityOptions.makeBasic()
options.setLockTaskEnabled(true)

// Start our kiosk app's main activity with our lock task mode option.
val packageManager = context.packageManager
val launchIntent = packageManager.getLaunchIntentForPackage(KIOSK_PACKAGE)
if (launchIntent != null) {
    context.startActivity(launchIntent, options.toBundle())
}

Java

// Set an option to turn on lock task mode when starting the activity.
ActivityOptions options = ActivityOptions.makeBasic();
options.setLockTaskEnabled(true);

// Start our kiosk app's main activity with our lock task mode option.
PackageManager packageManager = context.getPackageManager();
Intent launchIntent = packageManager.getLaunchIntentForPackage(KIOSK_PACKAGE);
if (launchIntent != null) {
  context.startActivity(launchIntent, options.toBundle());
}

En las versiones de Android anteriores a la 9.0, una app llama a Activity.startLockTask() para iniciar sus propias actividades en el modo de tareas bloqueadas. Para llamar a este método, la actividad debe ejecutarse en primer plano (consulta Conceptos del ciclo de vida de la actividad), por lo que te sugerimos llamar al método onResume() de Activity o Fragment. Sigue estos pasos para llamar a startLockTask():

Kotlin

// In our Fragment subclass.
override fun onResume() {
    super.onResume()
    // First, confirm that this package is allowlisted to run in lock task mode.
    if (dpm.isLockTaskPermitted(context.packageName)) {
        activity.startLockTask()
    } else {
        // Because the package isn't allowlisted, calling startLockTask() here
        // would put the activity into screen pinning mode.
    }
}

Java

// In our Fragment subclass.
@Override
public void onResume() {
  super.onResume();

  // First, confirm that this package is allowlisted to run in lock task mode.
  if (dpm.isLockTaskPermitted(context.getPackageName())) {
    getActivity().startLockTask();
  } else {
    // Because the package isn't allowlisted, calling startLockTask() here
    // would put the activity into screen pinning mode.
  }
}

No inicias el modo de tareas bloqueadas cuando el dispositivo está bloqueado, ya que es posible que el usuario no pueda desbloquearlo. Puedes llamar a los métodos KeyguardManager para averiguar si el dispositivo está bloqueado y usar una devolución de llamada de ciclo de vida Activity (como onResume(), que se llama después de desbloquearlo) para iniciar el modo de tareas bloqueadas.

Una app en el modo de tareas bloqueadas puede iniciar nuevas actividades, siempre y cuando esta no inicie una tarea nueva, excepto aquellas que inician una app incluida en la lista de entidades permitidas. Para comprender cómo se relacionan las tareas con las actividades, consulta la guía Información sobre las tareas y la pila de actividades.

De manera alternativa, puedes declarar en el archivo de manifiesto de la app cómo debe comportarse una actividad cuando el sistema se ejecuta en el modo de tareas bloqueadas. Para que el sistema ejecute automáticamente tu actividad en el modo de tareas bloqueadas, establece el atributo android:lockTaskMode en if_whitelisted, como se muestra en el siguiente ejemplo:

<activity
    android:name=".MainActivity"
    android:lockTaskMode="if_whitelisted">
    <!-- ... -->
</activity>

Si deseas obtener más información para declarar opciones en el archivo de manifiesto de la app, consulta la referencia de lockTaskMode.

Detener modo de tareas bloqueadas

Un DPC puede detener de forma remota el modo de tareas bloqueadas quitando el paquete de la app de la lista de entidades permitidas. Llama a DevicePolicyManager.setLockTaskPackages(), en Android 6.0 (nivel de API 23) o versiones posteriores, y omite el nombre del paquete en el array de la lista de entidades permitidas. Cuando actualizas la lista de entidades permitidas, la app vuelve a la tarea anterior de la pila.

Si una actividad antes llamaba startLockTask(), entonces puede llamar a Activity.stopLockTask() para detener el modo de tareas bloqueadas. Este método solo funciona para la actividad que inició el modo de tareas bloqueadas.

Devoluciones de llamada del ciclo de vida

Tu DPC puede resultarte útil saber cuándo una app (que se ejecuta en el mismo usuario) entra y sale del modo de tareas bloqueadas. Para recibir devoluciones de llamada, anula los siguientes métodos de devolución de llamada en la subclase DeviceAdminReceiver de tu DPC:

onLockTaskModeEntering()
Se llama después de que una app entra en el modo de tareas bloqueadas. Puedes obtener el nombre del paquete de una app a partir del argumento pkg.
onLockTaskModeExiting()
Se llama después de que una app sale del modo de tareas bloqueadas. Esta devolución de llamada no recibe información sobre la app.

Si inicias otra app en el modo de tareas bloqueadas, debes realizar un seguimiento del estado de ejecución en tu propia app. Para verificar si la app actual se ejecuta en este modo, usa los métodos en ActivityManager como se muestra en el siguiente ejemplo:

Kotlin

// Check if this app is in lock task mode. Screen pinning doesn't count.
var isLockTaskModeRunning = false

val activityManager = context
        .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    isLockTaskModeRunning =
            activityManager.lockTaskModeState ==
            ActivityManager.LOCK_TASK_MODE_LOCKED
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Deprecated in API level 23.
    isLockTaskModeRunning = activityManager.isInLockTaskMode
}

if (isLockTaskModeRunning) {
    // Show the exit button ...
}

Java

// Check if this app is in lock task mode. Screen pinning doesn't count.
boolean isLockTaskModeRunning = false;

ActivityManager activityManager = (ActivityManager)
    getContext().getSystemService(Context.ACTIVITY_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  isLockTaskModeRunning = activityManager.getLockTaskModeState()
      == ActivityManager.LOCK_TASK_MODE_LOCKED;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  // Deprecated in API level 23.
  isLockTaskModeRunning = activityManager.isInLockTaskMode();
}

if (isLockTaskModeRunning) {
  // Show the exit button ...
}

Personaliza la IU

Cuando una app se ejecuta en este modo, la interfaz de usuario (IU) del sistema cambia de las siguientes maneras:

  • La barra de estado está en blanco y las notificaciones y la información del sistema están ocultas.
  • Los botones Home y Overview están ocultos.
  • Otras apps no pueden iniciar nuevas actividades.
  • La pantalla de bloqueo (si está configurada) está inhabilitada.

En Android 9.0 o versiones posteriores, cuando el modo de tareas bloqueadas está habilitado, tu DPC puede habilitar ciertas funciones de la IU del sistema en el dispositivo, lo que resulta útil para los desarrolladores que crean un selector personalizado. Llama a DevicePolicyManager.setLockTaskFeatures() como se muestra en el siguiente fragmento:

Kotlin

// Enable the Home and Overview buttons so that our custom launcher can respond
// using our custom activities. Implicitly disables all other features.
dpm.setLockTaskFeatures(
        adminName,
        DevicePolicyManager.LOCK_TASK_FEATURE_HOME or
              DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW)

Java

// Enable the Home and Overview buttons so that our custom launcher can respond
// using our custom activities. Implicitly disables all other features.
dpm.setLockTaskFeatures(adminName,
    DevicePolicyManager.LOCK_TASK_FEATURE_HOME |
          DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW);

El sistema inhabilita todas las funciones que no incluyas en el argumento de flags. Las funciones de la IU habilitadas se conservan entre inicios en el modo de tareas bloqueadas. Si el dispositivo ya se encuentra en este modo, los cambios que realices en las funciones de tareas bloqueadas se mostrarán de inmediato. En la Tabla 2, se describen las funciones de la IU que puedes personalizar.

Tabla 2: Funciones personalizables de la IU del sistema en el modo de tareas bloqueadas
Función de IU del sistema Descripción
LOCK_TASK_FEATURE_HOME Muestra el botón de inicio. Habilitar para los selectores personalizados: presionar un botón de inicio habilitado no tiene ninguna acción, a menos que incluyas el selector de Android predeterminado en la lista de entidades permitidas.
LOCK_TASK_FEATURE_OVERVIEW Muestra el botón Recientes (si presionas este botón, se abre la pantalla Recientes). Si habilitas este botón, también debes habilitar el botón de inicio.
LOCK_TASK_FEATURE_GLOBAL_ACTIONS Habilita el diálogo de acciones globales que se muestra cuando se mantiene presionado el botón de encendido. Es la única función que se habilita cuando no se ha llamado a setLockTaskFeatures(). Por lo general, los usuarios no pueden apagar el dispositivo si inhabilitas este diálogo.
LOCK_TASK_FEATURE_NOTIFICATIONS Habilita las notificaciones para todas las apps. Muestra los íconos de notificaciones en la barra de estado, las notificaciones emergentes y el panel de notificaciones expandible. Si habilitas este botón, también debes habilitar el botón de inicio. Si se presionan las acciones de notificaciones y los botones que abren nuevos paneles, no funciona en el modo de tareas bloqueadas.
LOCK_TASK_FEATURE_SYSTEM_INFO Habilita el área de información del sistema de la barra de estado que contiene indicadores, como las opciones de conectividad, batería y sonido y vibración.
LOCK_TASK_FEATURE_KEYGUARD Habilita cualquier pantalla de bloqueo que pueda estar configurada en el dispositivo. Por lo general, no es adecuado para dispositivos con usuarios públicos, como kioscos de información o señalización digital.
LOCK_TASK_FEATURE_NONE Inhabilita todas las funciones de la IU del sistema mencionadas anteriormente.

Un DPC puede llamar a DevicePolicyManager.getLockTaskFeatures() para obtener la lista de funciones disponibles en un dispositivo cuando se habilita el modo de tareas bloqueadas. Cuando un dispositivo sale del modo de tareas bloqueadas, la interfaz de usuario vuelve al estado que exigen las políticas de dispositivos existentes.

Bloquear ventanas y superposiciones

Cuando una app se ejecuta en este modo, otras apps y servicios en segundo plano pueden crear ventanas nuevas que Android muestra frente a ella en ese modo. Las apps y los servicios crean estas ventanas para mostrar avisos, diálogos y superposiciones a la persona que usa el dispositivo. Tu DPC puede evitar esto agregando la restricción de usuario de DISALLOW_CREATE_WINDOWS. En el siguiente ejemplo, se muestra cómo podrías hacerlo en la devolución de llamada onLockTaskModeEntering():

Kotlin

// Called just after entering lock task mode.
override fun onLockTaskModeEntering(context: Context, intent: Intent) {
    val dpm = getManager(context)
    val admin = getWho(context)

    dpm.addUserRestriction(admin, UserManager.DISALLOW_CREATE_WINDOWS)
}

Java

// Called just after entering lock task mode.
public void onLockTaskModeEntering(Context context, Intent intent) {
  DevicePolicyManager dpm = getManager(context);
  ComponentName admin = getWho(context);

  dpm.addUserRestriction(admin, UserManager.DISALLOW_CREATE_WINDOWS);
}

Tu DPC puede quitar la restricción del usuario cuando el dispositivo sale del modo de tareas bloqueadas.

Recursos adicionales

Para obtener más información sobre los dispositivos exclusivos, consulta los siguientes documentos: