Como criar apps baseados em vários usuários

Quando um dispositivo oferece suporte a vários usuários, os apps precisam ser esses usuários distintos.

Certos apps precisam ter componentes executados como Singletons e podem aceitar solicitações de qualquer usuário. Apenas aplicativos do sistema podem usar esse recurso no momento.

Essa instalação:

  • Economizam recursos
  • Arbitra um ou mais recursos compartilhados entre usuários
  • Reduz a sobrecarga da rede usando uma única conexão de servidor

No diagrama abaixo, há uma representação do fluxo de permissões com vários usuários.

Fluxo de permissões para vários usuários

Figura 1. Permissões para vários usuários

Como ativar um componente singleton

Para identificar um app como Singleton, adicione android:singleUser="true" ao seu serviço. receptor ou provedor no manifesto do Android.

O sistema vai instanciar esse componente no processo executado como usuário 0. . Todas as solicitações para se conectar a esse provedor ou serviço, ou para transmitir para esse receptor, qualquer usuário será encaminhado para o processo no usuário 0. Se esse for o único componente do app, apenas uma instância do seu app será executada.

As atividades no seu pacote ainda serão iniciadas em um processo separado para cada usuário, com o UID no intervalo de UID para esse usuário (como 1010034).

Interação com usuários

Definir permissões

Essas permissões são obrigatórias

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Empregar APIs

Use as APIs a seguir para informar vários usuários aos apps.

  1. Extraia o identificador do usuário das chamadas de vinculação recebidas:
    • int userHandle = UserHandle.getCallingUserId()
  2. Use APIs novas e protegidas para iniciar serviços, atividades e transmissões em um usuário:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    . UserHandle pode ser um usuário explícito ou um dos identificadores especiais: UserHandle.CURRENT ou UserHandle.ALL. CURRENT indica o usuário que está em primeiro plano. Use ALL quando quiser enviar uma transmissão para todos os usuários.
  3. Comunicar-se com componentes no seu app: (INTERACT_ACROSS_USERS) Ou com componentes em outros apps: (INTERACT_ACROSS_USERS_FULL)
  4. Talvez seja necessário criar componentes de proxy que sejam executados no processo do usuário e que e acessar o componente singleUser no usuário 0.
  5. Consulte usuários e identificadores com o novo serviço do sistema UserManager:
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle): um número não reciclado que corresponde a um identificador de usuário.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() : retorna o conjunto de perfis próprios e gerenciados, se houver.
  6. Registre-se para detectar usuários específicos ou todos e os callbacks com novas APIs em ContentObserver, PackageMonitor e BroadcastReceiver, que fornecem informações sobre qual usuário causou o callback.

Serviços em vários usuários ou perfis

Nem todos os serviços precisam executar uma instância em outro usuário ou perfil de trabalho. Se o serviço do sistema só precisa ser executado como usuário 0, desative os componentes do serviço ao ser executado em outros usuários para ajudar a preservar os recursos. O exemplo a seguir mostra como fazer isso na entrada do seu serviço pontos:

// Add on all entry points such as boot_completed or other manifest-listed receivers and providers
if (!UserManager.isSystemUser()) {
    // Disable the service
    ComponentName targetServiceName = new ComponentName(this, TargetService.class);
    context.getPackageManager().setComponentEnabledSetting(
        targetServiceName, COMPONENT_ENABLED_STATE_DISABLED, 0);
}

O exemplo também pode usar PackageManager.setApplicationEnabledSetting() para desativar o app inteiro.