Creación de aplicaciones multiusuario

Cuando un dispositivo admite varios usuarios , sus aplicaciones deben tener en cuenta estos distintos usuarios.

Ciertas aplicaciones necesitan que algunos componentes se ejecuten como singleton y puedan 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 diagrama siguiente para obtener una descripción del flujo de permisos con varios usuarios.

Flujo de permisos de múltiples usuarios

Figura 1. Permisos de múltiples usuarios

Habilitar 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 creará una instancia de 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, desde cualquier usuario se enrutará al proceso en el usuario 0. Si este es el único componente de su aplicación, solo se ejecutará una instancia de su aplicación.

Las actividades de su paquete se seguirán iniciando en un proceso separado para cada usuario, con el UID dentro del 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 a varios usuarios.

  1. Extraiga el identificador de usuario de las llamadas entrantes de Binder:
    • int userHandle = UserHandle.getCallingUserId()
  2. Utilice API nuevas y protegidas para iniciar servicios, actividades y transmisiones para 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 se encuentra actualmente en primer plano. Utilice ALL cuando desee enviar una transmisión a todos los usuarios.
  3. Comunicarse con componentes en su propia aplicación: (INTERACT_ACROSS_USERS) O con componentes en otras aplicaciones: (INTERACT_ACROSS_USERS_FULL)
  4. Es posible que necesite crear componentes proxy que se ejecuten en el proceso del usuario y que luego accedan al componente 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 los hay.
  6. Regístrese para escuchar a usuarios específicos o a todos y las devoluciones de llamada con nuevas API en ContentObserver, PackageMonitor, BroadcastReceiver que brindan información adicional sobre qué usuario provocó 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 ejecute 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.