Creación de aplicaciones multiusuario

Cuando un dispositivo admite múltiples usuarios , sus aplicaciones deben ser conscientes de estos distintos usuarios.

Ciertas aplicaciones necesitan que algunos componentes se ejecuten como singletons y pueden aceptar solicitudes de cualquier usuario. Actualmente, solo las aplicaciones del sistema pueden usar esta función.

Esta instalación:

  • Conserva los recursos
  • Arbitra uno o más recursos compartidos entre usuarios
  • Reduce la sobrecarga de la red mediante el uso de una única conexión de servidor

Consulte el siguiente diagrama para ver una descripción del flujo de permisos con varios usuarios.

Flujo de permisos de múltiples usuarios

Figura 1. Permisos de múltiples usuarios

Habilitación de un componente singleton

Para identificar una aplicación como singleton, agregue android:singleUser=”true” a su servicio, receptor o proveedor en el manifiesto de Android.

El sistema instanciará ese componente en el proceso que se ejecuta solo como usuario 0. Cualquier solicitud para conectarse a ese proveedor o servicio, o para transmitir a ese receptor, de cualquier usuario se enrutará al proceso en el usuario 0. Si este es el único componente en su aplicación, solo se ejecutará una instancia de su aplicación.

Las actividades en su paquete aún se iniciarán en un proceso separado para cada usuario, con el UID en el rango de UID para ese usuario (como 1010034).

Interactuando con los usuarios

Establecer permisos

Estos permisos son necesarios

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Emplear API

Utilice las siguientes API para que las aplicaciones reconozcan la existencia de varios usuarios.

  1. Extraiga el identificador de usuario de las llamadas entrantes de Binder:
    • int userHandle = UserHandle.getCallingUserId()
  2. Use API nuevas y protegidas para iniciar servicios, actividades, transmisiones en un usuario específico:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    UserHandle puede ser un usuario explícito o uno de los identificadores especiales: UserHandle.CURRENT o UserHandle.ALL . CURRENT indica el usuario que está actualmente en primer plano. Use ALL cuando desee enviar una transmisión a todos los usuarios.
  3. Comuníquese con componentes en su propia aplicación: (INTERACT_ACROSS_USERS) O con componentes en otras aplicaciones: (INTERACT_ACROSS_USERS_FULL)
  4. Es posible que deba crear componentes de proxy que se ejecuten en el proceso del usuario y que luego accedan al componente de usuario singleUser en el usuario 0.
  5. Consulta a los usuarios y sus identificadores con el nuevo servicio del sistema UserManager :
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) - un número no reciclado que corresponde a un identificador de usuario.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() : devuelve la colección de perfiles propios y administrados, si corresponde.
  6. Regístrese para escuchar usuarios específicos o todos y las devoluciones de llamada con nuevas API en ContentObserver, PackageMonitor, BroadcastReceiver que brindan información adicional sobre qué usuario ha causado la devolución de llamada.

Servicios en múltiples usuarios o perfiles

No todos los servicios necesitan ejecutar una instancia en otro usuario o perfil de trabajo. Si el servicio de su sistema solo necesita ejecutarse como usuario 0, deshabilite los componentes del servicio cuando se ejecuta con otros usuarios para ayudar a preservar los recursos. El siguiente ejemplo muestra cómo puede hacer esto en los puntos de entrada de su servicio:

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

El ejemplo también podría usar PackageManager.setApplicationEnabledSetting() para deshabilitar toda la aplicación.