Creazione di app multiutente

Quando un dispositivo supporta più utenti , le sue app devono essere informate di questi utenti distinti.

Alcune app devono avere alcuni componenti eseguiti come singleton e possono accettare richieste da qualsiasi utente. Solo le app di sistema possono attualmente utilizzare questa funzionalità.

Questa struttura:

  • Conserva le risorse
  • Arbitra una o più risorse condivise tra gli utenti
  • Riduce il sovraccarico della rete utilizzando una singola connessione al server

Consulta il diagramma seguente per una rappresentazione del flusso di autorizzazioni con più utenti.

Flusso di autorizzazioni per più utenti

Figura 1. Autorizzazioni per più utenti

Abilitazione di un componente singleton

Per identificare un'app come singleton, aggiungi android:singleUser="true" al tuo servizio, ricevitore o provider nel manifest Android.

Il sistema creerà un'istanza di quel componente nel processo in esecuzione solo come utente 0. Qualsiasi richiesta di connessione a quel provider o servizio o di trasmissione a quel ricevitore da parte di qualsiasi utente verrà instradata al processo nell'utente 0. Se questo è l'unico componente nella tua app, verrà eseguita solo un'istanza della tua app.

Le attività nel pacchetto verranno comunque avviate in un processo separato per ciascun utente, con l'UID compreso nell'intervallo UID per quell'utente (ad esempio 1010034).

Interagire con gli utenti

Imposta le autorizzazioni

Queste autorizzazioni sono necessarie

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Utilizza le API

Utilizza le seguenti API per rendere le app consapevoli di più utenti.

  1. Estrai l'handle utente dalle chiamate Binder in entrata:
    • int userHandle = UserHandle.getCallingUserId()
  2. Utilizza API nuove e protette per avviare servizi, attività, trasmissioni su un utente specifico:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    UserHandle può essere un utente esplicito o uno degli handle speciali: UserHandle.CURRENT o UserHandle.ALL . CURRENT indica l'utente attualmente in primo piano. Utilizza ALL quando desideri inviare una trasmissione a tutti gli utenti.
  3. Comunica con i componenti nella tua app: (INTERACT_ACROSS_USERS) O con i componenti in altre app: (INTERACT_ACROSS_USERS_FULL)
  4. Potrebbe essere necessario creare componenti proxy eseguiti nel processo dell'utente che quindi accedono al componente singleUser nell'utente 0.
  5. Interroga gli utenti e i loro handle con il nuovo servizio di sistema UserManager :
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) - un numero non riciclato che corrisponde a un handle utente.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() - restituisce la raccolta di profili personali e gestiti, se presenti.
  6. Registrati per ascoltare utenti specifici o tutti e le richiamate con le nuove API su ContentObserver, PackageMonitor, BroadcastReceiver che forniscono informazioni aggiuntive su quale utente ha causato la richiamata.

Servizi in più utenti o profili

Non tutti i servizi devono eseguire un'istanza in un altro utente o profilo di lavoro. Se il servizio di sistema deve essere eseguito solo come utente 0, disabilita i componenti del servizio quando viene eseguito con altri utenti per preservare le risorse. L'esempio seguente mostra come potresti eseguire questa operazione nei punti di ingresso del tuo servizio:

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

L'esempio potrebbe anche utilizzare PackageManager.setApplicationEnabledSetting() per disabilitare l'intera app.