Quando un dispositivo supporta più utenti, le sue app devono essere consapevoli di questi utenti distinti.
Per alcune app è necessario che alcuni componenti vengano eseguiti come oggetti singoli e possano accettare richieste da qualsiasi utente. Al momento, solo le app di sistema possono utilizzare questa funzionalità.
Questa struttura:
- Risparmia risorse
- Gestisce 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 rappresentazione del flusso di autorizzazioni con più utenti.
Figura 1. Autorizzazioni per più utenti
Attivare un componente singleton
Per identificare un'app come singleton, aggiungi android:singleUser="true"
al servizio, al ricevitore o al provider nel file manifest di Android.
Il sistema esegue l'inizializzazione del componente nel processo in esecuzione solo come utente 0. Eventuali richieste di connessione a quel fornitore o servizio o di trasmissione a quel ricevitore da parte di qualsiasi utente vengono inoltrate al processo nell'utente 0. Se questo è l'unico componente dell'app, viene eseguita solo un'istanza dell'app.
Le attività nel pacchetto vengono comunque avviate in un processo separato per ciascun utente, con l'UID che rientra nell'intervallo UID dell'utente (ad esempio 1010034).
Interagire con gli utenti
Imposta autorizzazioni
Sono richieste le seguenti autorizzazioni:
INTERACT_ACROSS_USERS (signature|system) INTERACT_ACROSS_USERS_FULL (signature)
Utilizzare le API
Utilizza le seguenti API per rendere le app consapevoli della presenza di più utenti.
- Estrai l'handle utente dalle chiamate Binder in arrivo:
int userHandle = UserHandle.getCallingUserId()
- Utilizza nuove API protette per avviare servizi, attività e 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
oUserHandle.ALL
.CURRENT
indica l'utente attualmente in primo piano. UtilizzaALL
quando vuoi inviare una trasmissione a tutti gli utenti. - Comunica con i componenti della tua app:
(INTERACT_ACROSS_USERS)
O con i componenti di altre app:(INTERACT_ACROSS_USERS_FULL)
- Potresti dover creare componenti proxy che vengono eseguiti nel processo dell'utente e poi accedono al componente
singleUser
nell'utente 0. - Esegui query sugli utenti e sui relativi 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.
- Registrati per ascoltare utenti specifici o tutti gli utenti e i rilanci con nuove API su ContentObserver, PackageMonitor, BroadcastReceiver che forniscono informazioni aggiuntive su quale utente ha causato il richiamo.
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 contribuire a preservare le risorse. L'esempio seguente mostra come eseguire questa operazione nei punti di accesso del 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 disattivare
l'intera app.