Creare app multiutente-Aware

Se un dispositivo supporta più utenti, le relative app devono essere consapevoli di questi utenti distinti.

Alcune app devono avere alcuni componenti eseguiti come singleton e possono accettare richieste da parte di un qualsiasi utente. Al momento solo le app di sistema possono usare questa funzionalità.

Questa struttura:

  • Risparmia risorse
  • Arbita una o più risorse condivise tra gli utenti
  • Riduce l'overhead della rete utilizzando una singola connessione al server

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

Flusso di autorizzazioni per più utenti

Figura 1. Autorizzazioni di più utenti

Attivazione di un componente singleton

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

Il sistema creerà un'istanza del componente nel processo in esecuzione come utente 0. . Qualsiasi richiesta di connessione a quel fornitore o servizio o di trasmettere a quel destinatario, da qualsiasi utente verrà indirizzato al processo nell'utente 0. Se questo è l'unico componente della tua app, verrà eseguita una sola istanza dell'app.

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

Interazione con gli utenti

Imposta autorizzazioni

Queste autorizzazioni sono obbligatorie

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Utilizza le API

Utilizza le API riportate di seguito per segnalare alle app la presenza di più utenti.

  1. Estrai l'handle dell'utente dalle chiamate a Binder in arrivo:
    • int userHandle = UserHandle.getCallingUserId()
  2. Utilizza nuove API protette per avviare servizi, attività e trasmissioni su un utente:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    di Gemini Advanced. UserHandle può essere un utente esplicito o uno degli handle speciali: UserHandle.CURRENT o UserHandle.ALL. CURRENT indica l'utente attualmente in primo piano. Usa ALL quando vuoi inviare un annuncio a tutti gli utenti.
  3. Comunicare con i componenti nella tua app: (INTERACT_ACROSS_USERS) Oppure con i componenti in altre app: (INTERACT_ACROSS_USERS_FULL)
  4. Potrebbe essere necessario creare componenti proxy che vengono eseguiti nel processo dell'utente per quindi accedi al componente singleUser nell'utente 0.
  5. Esegui una query sugli utenti e sui 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 all'handle di un utente.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() : restituisce la raccolta degli eventuali profili personali e gestiti.
  6. Registrati per ascoltare utenti specifici o tutti e i callback con le nuove API su ContentObserver, PackageMonitor, BroadcastReceiver che forniscono informazioni su quale utente ha attivato 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, disattiva i componenti del servizio quando viene eseguito da altri utenti per preservare le risorse. L'esempio seguente mostra come eseguire questa operazione all'indirizzo del tuo servizio punti:

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

Nell'esempio potresti anche utilizzare PackageManager.setApplicationEnabledSetting() per disattivare dell'intera app.