Cuando un dispositivo admite varios usuarios, sus apps deben estar al tanto de estos usuarios distintos.
Algunas apps deben tener algunos componentes que se ejecuten como objetos singleton y que puedan aceptar solicitudes de cualquier usuario. Actualmente, solo las apps del sistema pueden usar esta función.
Esta instalación tiene las siguientes características:
- Conserva recursos
- Arbitra uno o más recursos compartidos entre los usuarios
- Reduce la sobrecarga de red mediante el uso de una sola conexión de servidor.
Consulta el siguiente diagrama para ver una representación del flujo de permisos con varios usuarios.
Figura 1: Permisos de varios usuarios
Habilita un componente singleton
Para identificar una app como singleton, agrega android:singleUser="true"
a tu servicio, receptor o proveedor en el manifiesto de Android.
El sistema crea 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 enruta al proceso en el usuario 0. Si este es el único componente de tu app, solo se ejecutará una instancia de la app.
Las actividades de tu paquete se inician en un proceso independiente para cada usuario, y el UID se encuentra en el rango de UID de ese usuario (como 1010034).
Interactuar con los usuarios
Configurar permisos
Se requieren los siguientes permisos:
INTERACT_ACROSS_USERS (signature|system) INTERACT_ACROSS_USERS_FULL (signature)
Usar APIs
Usa las siguientes APIs para que las apps detecten varios usuarios.
- Extrae el identificador de usuario de las llamadas entrantes de Binder:
int userHandle = UserHandle.getCallingUserId()
- Usa nuevas APIs protegidas para iniciar servicios, actividades y 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
oUserHandle.ALL
.CURRENT
indica el usuario que está en primer plano. UsaALL
cuando quieras enviar una transmisión a todos los usuarios. - Comunicarse con componentes de tu propia app:
(INTERACT_ACROSS_USERS)
O con componentes de otras apps:(INTERACT_ACROSS_USERS_FULL)
- Es posible que debas crear componentes de proxy que se ejecuten en el proceso del usuario y que, luego, accedan al componente
singleUser
en el usuario 0. - Consulta a los usuarios y sus identificadores con el nuevo servicio del sistema
UserManager
:UserManager.getUsers()
UserManager.getUserInfo()
UserManager.supportsMultipleUsers()
UserManager.getUserSerialNumber(int userHandle)
: Es un número no reciclado que corresponde a un identificador de usuario.UserManager.getUserHandle(int serialNumber)
UserManager.getUserProfiles()
: Muestra la colección de perfiles autoadministrados y administrados, si los hay.
- Regístrate para escuchar a usuarios específicos o a todos los usuarios y las devoluciones de llamada con nuevas APIs en ContentObserver, PackageMonitor y BroadcastReceiver que proporcionan información adicional sobre qué usuario causó la devolución de llamada.
Servicios en varios usuarios o perfiles
No todos los servicios necesitan ejecutar una instancia en otro usuario o perfil de trabajo. Si el servicio del sistema solo necesita ejecutarse como el usuario 0, inhabilita los componentes del servicio cuando se ejecute en otros usuarios para ayudar a preservar los recursos. En el siguiente ejemplo, se muestra cómo puedes hacerlo en los puntos de entrada de tu 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 inhabilitar
toda la app.