Modo de bloqueio de tarefas

Este guia para desenvolvedores explica como dispositivos dedicados podem ser bloqueados em um único app ou conjunto de apps. Se você é um desenvolvedor de gerenciamento de mobilidade empresarial (EMM, na sigla em inglês) ou integrador de soluções, leia este guia para adicionar o modo de tarefa de bloqueio à sua solução.

Visão geral

O Android pode executar tarefas de maneira imersiva, semelhante à forma de quiosque, com o modo de bloqueio de tarefas. É possível usar o modo de bloqueio de tarefas se estiver desenvolvendo um aplicativo de quiosque ou uma tela de início para apresentar uma coleção de apps. Quando o sistema é executado no modo de bloqueio de tarefas, os usuários do dispositivo normalmente não podem receber notificações, acessar apps que não estejam na lista de permissões nem voltar à tela inicial, a menos que ela esteja na lista de permissões.

Somente apps na lista de permissões por um controlador de política de dispositivo (DPC) podem ser executados quando o sistema está no modo de bloqueio de tarefas. Os apps são incluídos na lista de permissões porque o usuário do dispositivo nem sempre pode sair do modo de bloqueio de tarefas.

A forma como você combina o app na lista de permissões para o modo de tarefa de bloqueio e o DPC na lista de permissões vai depender do problema que você quer resolver. Veja alguns exemplos:

  • Um único pacote de apps que combina um quiosque para apresentar conteúdo e um miniDPC (para adicionar à lista de permissões o modo de bloqueio de tarefas).
  • Um DPC que faz parte de uma solução de gerenciamento de mobilidade empresarial, iniciando os apps para dispositivos móveis do cliente no modo de bloqueio de tarefas.

Disponibilidade

O sistema pode ser executado no modo de bloqueio de tarefas no Android 5.0 ou mais recente. A Tabela 1 mostra quais versões do Android são compatíveis com a lista de permissões por usuário.

Tabela 1. Suporte à versão do Android para os modos de administrador do DPC
Versão do Android Administrações de DPC Notes
Android 5.0 (nível 21 da API) ou mais recente Dispositivo totalmente gerenciado
Android 8.0 (API de nível 26) ou mais recente Usuário secundário afiliado O usuário secundário precisa estar afiliado ao usuário principal. Consulte a visão geral de vários usuários.
Android 9.0 (API de nível 28) ou mais recente Usuário secundário

No Android 9.0 ou versões mais recentes, um DPC pode iniciar a atividade de qualquer app no modo de bloqueio de tarefas. Nas versões anteriores, o app já precisa ser compatível com a inicialização da própria atividade no modo de bloqueio de tarefas.

Colocar apps na lista de permissões

Um DPC precisa colocar os apps na lista de permissões antes que eles possam ser usados no modo de bloqueio de tarefas. Chame DevicePolicyManager.setLockTaskPackages() para adicionar apps à lista de permissões para o modo de tarefa de bloqueio, conforme mostrado no exemplo a seguir:

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 descobrir os apps anteriormente permitidos para o modo de bloqueio de tarefas, um DPC pode chamar DevicePolicyManager.getLockTaskPackages(). Outros apps podem chamar DevicePolicyManager.isLockTaskPermitted() para confirmar se um pacote de app oferece suporte ao modo de bloqueio de tarefas.

Iniciar modo de bloqueio de tarefas

No Android 9.0 (API de nível 28) ou versões mais recentes, você pode iniciar a atividade de outro app no modo de bloqueio de tarefas. Se uma atividade já estiver sendo executada em primeiro ou segundo plano, ela precisará ser reiniciada. Chame ActivityOptions.setLockTaskEnabled() e forneça essas opções ao iniciar a atividade. O snippet a seguir mostra uma maneira de fazer isso:

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

Nas versões do Android anteriores à 9.0, um app inicia as próprias atividades no modo de bloqueio de tarefas chamando Activity.startLockTask(). Para chamar esse método, a atividade precisa estar em execução em primeiro plano. Consulte Conceitos do ciclo de vida da atividade. Portanto, sugerimos chamar o método onResume() de uma Activity ou Fragment. Veja como você pode ligar para 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.
  }
}

Não inicie o modo de tarefa de bloqueio quando o dispositivo estiver bloqueado, porque o usuário pode não conseguir desbloquear o dispositivo. Você pode chamar métodos KeyguardManager para descobrir se o dispositivo está bloqueado e usar um callback de ciclo de vida de Activity (como onResume(), que é chamado após o desbloqueio) para iniciar o modo de bloqueio de tarefas.

Um app no modo de bloqueio de atividades pode iniciar novas atividades desde que a atividade não inicie uma nova tarefa, exceto tarefas que iniciem um app da lista de permissões. Para entender como as tarefas estão relacionadas às atividades, leia o guia Entender as tarefas e a backstack.

Como alternativa, é possível declarar no arquivo de manifesto do app como uma atividade vai se comportar quando o sistema estiver sendo executado no modo de bloqueio de tarefas. Para que o sistema execute automaticamente a atividade no modo de bloqueio de tarefas, defina o atributo android:lockTaskMode como if_whitelisted, conforme mostrado no exemplo a seguir.

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

Para saber mais sobre a declaração de opções no arquivo de manifesto do app, leia a referência lockTaskMode.

Parar o modo de bloqueio de tarefas

Um DPC pode interromper remotamente o modo de bloqueio de tarefas removendo o pacote de apps da lista de permissões. Chame DevicePolicyManager.setLockTaskPackages() no Android 6.0 (API de nível 23) ou mais recente e omita o nome do pacote da matriz da lista de permissões. Quando você atualiza a lista de permissões, o app retorna à tarefa anterior na pilha.

Se uma atividade chamava startLockTask(), ela pode chamar Activity.stopLockTask() para interromper o modo de bloqueio de tarefas. Esse método funciona apenas para a atividade que iniciou o modo de bloqueio de tarefas.

Callbacks do ciclo de vida

Pode ser útil saber quando um app (em execução no mesmo usuário) entra e sai do modo de bloqueio de tarefas. Para receber callbacks, modifique os métodos de callback abaixo na subclasse DeviceAdminReceiver do DPC:

onLockTaskModeEntering()
Chamado depois que um app entra no modo de bloqueio de tarefas. É possível conseguir o nome do pacote de um app usando o argumento pkg.
onLockTaskModeExiting()
Chamado depois que um app sai do modo de bloqueio de tarefas. Esse callback não recebe informações sobre o app.

Se você iniciar outro app no modo de bloqueio de tarefas, será necessário monitorar o status de execução no seu próprio app. Para conferir se o app atual está sendo executado no modo de bloqueio de tarefas, use os métodos em ActivityManager, conforme mostrado no exemplo a seguir:

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

Personalizar a interface

Quando um app é executado no modo de tarefa de bloqueio, a interface do usuário (IU) do sistema muda destas maneiras:

  • A barra de status fica em branco, com notificações e informações do sistema ocultas.
  • Os botões "Página inicial" e "Visão geral" estão ocultos.
  • Outros apps não podem iniciar novas atividades.
  • Se definida, a tela de bloqueio será desativada.

No Android 9.0 ou versões mais recentes, quando o modo de bloqueio de tarefas está ativado, seu DPC pode ativar determinados recursos de IU do sistema no dispositivo, o que é útil para desenvolvedores que criam uma tela de início personalizada. Chame DevicePolicyManager.setLockTaskFeatures() conforme mostrado no snippet a seguir:

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

O sistema desativa todos os recursos que você não inclui no argumento flags. Os recursos de interface ativados persistem entre as inicializações no modo de bloqueio de tarefas. Se o dispositivo já estiver no modo de tarefa de bloqueio, todas as mudanças feitas nos recursos da tarefa de bloqueio serão mostradas imediatamente. A Tabela 2 descreve os recursos da IU que você pode personalizar.

Tabela 2. Recursos personalizáveis da IU do sistema no modo de tarefa de bloqueio
Recurso de interface do sistema Descrição
LOCK_TASK_FEATURE_HOME Mostra o botão home. Ativar para telas de início personalizadas: tocar em um botão home ativado não faz nada, a menos que você adicione a tela de início padrão do Android à lista de permissões.
LOCK_TASK_FEATURE_OVERVIEW Mostra o botão "Visão geral". Um toque nesse botão abre a tela Recentes. Se você ativar esse botão, também vai precisar ativar o botão home.
LOCK_TASK_FEATURE_GLOBAL_ACTIONS Ativa a caixa de diálogo de ações globais que aparece ao manter o botão liga/desliga pressionado. O único recurso ativado quando setLockTaskFeatures() não é chamado. Um usuário normalmente não consegue desligar o dispositivo quando você desativa essa caixa de diálogo.
LOCK_TASK_FEATURE_NOTIFICATIONS Ativa as notificações para todos os apps. Isso mostra ícones de notificação na barra de status, notificações de alerta e aba de notificações expansível. Se você ativar esse botão, também vai precisar ativar o botão home. O toque em ações de notificação e em botões que abrem novos painéis não funciona no modo de bloqueio de tarefas.
LOCK_TASK_FEATURE_SYSTEM_INFO Ativa a área de informações do sistema da barra de status, que contém indicadores, como conectividade, bateria e opções de som e vibração.
LOCK_TASK_FEATURE_KEYGUARD Ativa qualquer tela de bloqueio que possa ser definida no dispositivo. Normalmente, não é adequado para dispositivos com usuários públicos, como quiosques de informações ou sinalização digital.
LOCK_TASK_FEATURE_NONE Desativa todos os recursos de interface do sistema listados acima.

Um DPC pode chamar DevicePolicyManager.getLockTaskFeatures() para conferir a lista de recursos disponíveis em um dispositivo quando o modo de bloqueio de tarefas está ativado. Quando um dispositivo sai do modo de tarefa de bloqueio, a interface do usuário retorna ao estado determinado pelas políticas do dispositivo.

Bloquear janelas e sobreposições

Quando um app é executado no modo de tarefa de bloqueio, outros apps e serviços em segundo plano podem criar novas janelas que o Android exibe na frente do app no modo de bloqueio de tarefas. Apps e serviços criam essas janelas para mostrar avisos, caixas de diálogo e sobreposições à pessoa que usa o dispositivo. O DPC pode evitar isso adicionando a restrição de usuário DISALLOW_CREATE_WINDOWS. O exemplo abaixo mostra como fazer isso no callback 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);
}

O DPC pode remover a restrição de usuário quando o dispositivo sair do modo de bloqueio de tarefas.

Outros recursos

Para saber mais sobre dispositivos dedicados, leia os seguintes documentos: