Questa guida per gli sviluppatori spiega in che modo il controller dei criteri dei dispositivi (DPC) può gestire più utenti Android su dispositivi dedicati.
Panoramica
Il tuo DPC può aiutare più persone a condividere un singolo dispositivo dedicato. Il tuo DPC (controller criteri dispositivi) in esecuzione su un dispositivo completamente gestito può creare e gestire due tipi di utenti:
- Gli utenti secondari sono utenti Android che hanno salvato app e dati separati. tra una sessione e l'altra. Per gestire l'utente devi utilizzare un componente di amministrazione. Questi utenti sono utile nei casi in cui un dispositivo viene rilevato all'inizio di un turno, come addetti alle consegne o addetti alla sicurezza.
- Gli utenti temporanei sono utenti secondari che il sistema elimina quando l'utente. si arresta, si allontana o il dispositivo si riavvia. Questi utenti sono utili per i casi in cui i dati possono essere eliminati al termine della sessione, ad esempio l'accesso pubblico kiosk internet.
Utilizzi il DPC esistente per gestire il dispositivo dedicato e utenti. Un componente amministratore nel DPC si imposta come amministratore per il nuovo gli utenti quando li crei.
.Gli amministratori di un utente secondario devono appartenere allo stesso pacchetto dell'amministratore di dispositivo completamente gestito. Per semplificare lo sviluppo, ti consigliamo di condividere un amministratore tra il dispositivo e gli utenti secondari.
Per gestire più utenti su dispositivi dedicati, in genere è richiesto Android 9.0, tuttavia alcuni dei metodi utilizzati in questa guida per gli sviluppatori sono disponibili in con le versioni precedenti di Android.
Utenti secondari
Gli utenti secondari possono connettersi al Wi-Fi e configurare nuove reti. Tuttavia, non possono modificare o eliminare le reti, neanche quelle che hanno creato.
Creare utenti
Il DPC può creare utenti aggiuntivi in background e poi può cambiarli in primo piano. Il processo è quasi lo stesso sia per gli ambienti secondari per gli utenti temporanei. Implementa i seguenti passaggi negli amministratori del servizio dispositivo gestito e utente secondario:
- Chiama il numero
DevicePolicyManager.createAndManageUser()
. Per creare un utente temporaneo, includiMAKE_USER_EPHEMERAL
nell'argomento flags. - Chiama
Da
DevicePolicyManager.startUserInBackground()
a avviare l'utente in background. L'utente inizia a correre, ma vuoi per completare la configurazione prima di portare l'utente in primo piano e mostrarlo a la persona che utilizza il dispositivo. - Nell'amministratore dell'utente secondario, chiama
Da
DevicePolicyManager.setAffiliationIds()
a abbinare il nuovo utente all'utente principale. Consulta Coordinazione DPC di seguito. - Torna all'amministratore del dispositivo completamente gestito, chiama
DevicePolicyManager.switchUser()
per consentire all'utente di passare in primo piano.
Il seguente esempio mostra come aggiungere il passaggio 1 al DPC:
Kotlin
val dpm = getContext().getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager // If possible, reuse an existing affiliation ID across the // primary user and (later) the ephemeral user. val identifiers = dpm.getAffiliationIds(adminName) if (identifiers.isEmpty()) { identifiers.add(UUID.randomUUID().toString()) dpm.setAffiliationIds(adminName, identifiers) } // Pass an affiliation ID to the ephemeral user in the admin extras. val adminExtras = PersistableBundle() adminExtras.putString(AFFILIATION_ID_KEY, identifiers.first()) // Include any other config for the new user here ... // Create the ephemeral user, using this component as the admin. try { val ephemeralUser = dpm.createAndManageUser( adminName, "tmp_user", adminName, adminExtras, DevicePolicyManager.MAKE_USER_EPHEMERAL or DevicePolicyManager.SKIP_SETUP_WIZARD) } catch (e: UserManager.UserOperationException) { if (e.userOperationResult == UserManager.USER_OPERATION_ERROR_MAX_USERS) { // Find a way to free up users... } }
Java
DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE); // If possible, reuse an existing affiliation ID across the // primary user and (later) the ephemeral user. Set<String> identifiers = dpm.getAffiliationIds(adminName); if (identifiers.isEmpty()) { identifiers.add(UUID.randomUUID().toString()); dpm.setAffiliationIds(adminName, identifiers); } // Pass an affiliation ID to the ephemeral user in the admin extras. PersistableBundle adminExtras = new PersistableBundle(); adminExtras.putString(AFFILIATION_ID_KEY, identifiers.iterator().next()); // Include any other config for the new user here ... // Create the ephemeral user, using this component as the admin. try { UserHandle ephemeralUser = dpm.createAndManageUser( adminName, "tmp_user", adminName, adminExtras, DevicePolicyManager.MAKE_USER_EPHEMERAL | DevicePolicyManager.SKIP_SETUP_WIZARD); } catch (UserManager.UserOperationException e) { if (e.getUserOperationResult() == UserManager.USER_OPERATION_ERROR_MAX_USERS) { // Find a way to free up users... } }
Quando crei o avvii un nuovo utente, puoi verificare il motivo degli eventuali errori
rilevando l'eccezione UserOperationException
e chiamando
getUserOperationResult()
. Numero di utenti in eccesso
sono motivi comuni di errore:
La creazione di un utente può richiedere del tempo. Se crei spesso utenti, puoi migliorare l'esperienza utente preparando un utente pronto all'uso in background. Potrebbe essere necessario bilanciare i vantaggi di un utente pronto all'uso con il massimo di utenti consentiti su un dispositivo.
Identificazione
Dopo aver creato un nuovo utente, devi indirizzare a quest'ultimo con un numero seriale permanente.
numero. Non rendere permanente UserHandle
perché il sistema ricicla questi elementi mentre
creare ed eliminare utenti. Recupera il numero di serie chiamando
UserManager.getSerialNumberForUser()
:
Kotlin
// After calling createAndManageUser() use a device-unique serial number // (that isn’t recycled) to identify the new user. secondaryUser?.let { val userManager = getContext().getSystemService(UserManager::class.java) val ephemeralUserId = userManager!!.getSerialNumberForUser(it) // Save the serial number to storage ... }
Java
// After calling createAndManageUser() use a device-unique serial number // (that isn’t recycled) to identify the new user. if (secondaryUser != null) { UserManager userManager = getContext().getSystemService(UserManager.class); long ephemeralUserId = userManager.getSerialNumberForUser(secondaryUser); // Save the serial number to storage ... }
Configurazione utente
A seconda delle esigenze degli utenti, puoi personalizzare la configurazione di
utenti. Puoi includere i seguenti flag quando chiami createAndManageUser()
:
SKIP_SETUP_WIZARD
- Salta l'esecuzione della configurazione guidata per i nuovi utenti, che verifica la presenza di aggiornamenti e li installa, chiede all'utente di aggiungere un Account Google insieme ai servizi Google e imposta un blocco schermo. Questa operazione può richiedere del tempo e potrebbe non essere applicabile a tutti ad esempio i kiosk internet pubblici.
LEAVE_ALL_SYSTEM_APPS_ENABLED
- Lascia tutte le app di sistema attivate nel nuovo utente. Se non imposti questo flag, il nuovo utente contiene solo l'insieme minimo di app di cui il telefono ha bisogno funzionano, in genere un browser di file, un tastierino telefonico, contatti e SMS.
Segui il ciclo di vita dell'utente
Il tuo DPC (se è un amministratore del dispositivo completamente gestito) potrebbe trovare utile
sapere quando cambiano utenti secondari. Per eseguire attività successive dopo le modifiche, sostituisci
questi metodi di callback nella sottoclasse DeviceAdminReceiver
del tuo DPC:
onUserStarted()
- Chiamato dopo che il sistema ha avviato un utente. L'utente potrebbe ancora configurare o
in esecuzione in background. Puoi recuperare l'utente da
startedUser
. onUserSwitched()
- Chiamato dopo che il sistema è passato a un altro utente. Puoi far arrivare il nuovo utente
attualmente in esecuzione in primo piano dall'argomento
switchedUser
. onUserStopped()
- Chiamata dopo che il sistema ha interrotto un utente perché è disconnesso, è passato a un
nuovo utente (se l'utente è temporaneo) o il tuo DPC ha arrestato l'utente. Puoi ottenere
l'utente dall'argomento
stoppedUser
. onUserAdded()
- Chiamato quando il sistema aggiunge un nuovo utente. In genere, gli utenti secondari non
completamente configurato quando il DPC
riceve la richiamata. Puoi far accedere l'utente
newUser
argomento. onUserRemoved()
- Chiamato dopo l'eliminazione di un utente da parte del sistema. Poiché l'utente è già stato eliminato,
Non puoi accedere all'utente rappresentato dall'argomento
removedUser
.
Per sapere quando il sistema mette un utente in primo piano o lo reindirizza allo
le app possono registrare un ricevitore
ACTION_USER_FOREGROUND
e
ACTION_USER_BACKGROUND
annunci.
Scopri gli utenti
Per recuperare tutti gli utenti secondari, un amministratore di un dispositivo completamente gestito può chiamare
DevicePolicyManager.getSecondaryUsers()
I risultati
include gli utenti secondari o temporanei creati dall'amministratore. Anche i risultati
Includono eventuali utenti secondari (o utenti ospiti) che una persona che utilizza il dispositivo potrebbe
che hai creato. I risultati non includono profili di lavoro perché non sono
utenti secondari. Il seguente esempio mostra come utilizzare questo metodo:
Kotlin
// The device is stored for the night. Stop all running secondary users. dpm.getSecondaryUsers(adminName).forEach { dpm.stopUser(adminName, it) }
Java
// The device is stored for the night. Stop all running secondary users. for (UserHandle user : dpm.getSecondaryUsers(adminName)) { dpm.stopUser(adminName, user); }
Di seguito sono riportati altri metodi che puoi chiamare per scoprire lo stato degli utenti secondari:
DevicePolicyManager.isEphemeralUser()
- Chiama questo metodo dall'amministratore di un utente secondario per scoprire se si tratta di un utente temporaneo.
DevicePolicyManager.isAffiliatedUser()
- Chiama questo metodo dall'amministratore di un utente secondario per sapere se questo utente affiliato all'utente principale. Per scoprire di più sull'affiliazione, consulta la sezione DPC (controller criteri dispositivi) di coordinamento di seguito.
Gestione utenti
Se vuoi gestire completamente il ciclo di vita dell'utente, puoi chiamare le API per un controllo granulare di quando e come il dispositivo cambia utente. Ad esempio, puoi eliminare un utente quando un dispositivo non è stato utilizzato per un certo periodo di tempo inviare ordini non inviati a un server prima che finisca il turno di una persona.
Esci
Android 9.0 ha aggiunto un pulsante di disconnessione alla schermata di blocco in modo che una persona che utilizza dispositivo può terminare la sessione. Dopo aver toccato il pulsante, il sistema interrompe la utente secondario, elimina l'utente se è temporaneo e l'utente principale torna in primo piano. Android nasconde il pulsante quando l'utente principale è in primo piano perché l'utente principale non riesce a uscire.
Android non mostra il pulsante di fine sessione per impostazione predefinita, ma l'amministratore (di un
completamente gestito) può abilitarlo chiamando
DevicePolicyManager.setLogoutEnabled()
Per
conferma lo stato attuale del pulsante, richiama
DevicePolicyManager.isLogoutEnabled()
L'amministratore di un utente secondario può disconnettere in modo programmatico l'utente e tornare
per l'utente principale. Innanzitutto, verifica che gli utenti secondari e principali siano
affiliato, quindi chiama DevicePolicyManager.logoutUser()
. Se
l'utente disconnesso è un utente temporaneo, il sistema arresta ed elimina
utente.
Cambia utente
Per passare a un altro utente secondario, l'amministratore di un dispositivo completamente gestito può
chiama DevicePolicyManager.switchUser()
. Per praticità, puoi
può passare null
per passare all'utente principale.
Interrompere un utente
Per interrompere un utente secondario, un DPC che possiede un dispositivo completamente gestito può chiamare
DevicePolicyManager.stopUser()
Se l'utente bloccato è
utente temporaneo, l'utente viene interrotto e poi eliminato.
Ti consigliamo di fermare gli utenti quando possibile per evitare di rimanere al di sotto della soglia il numero massimo di utenti in esecuzione.
Eliminazione di un utente
Per eliminare definitivamente un utente secondario, un DPC può chiamare uno dei seguenti
DevicePolicyManager
metodi:
- L'amministratore di un dispositivo completamente gestito può chiamare
removeUser()
. - Un amministratore dell'utente secondario può chiamare
wipeData()
.
Il sistema elimina gli utenti temporanei quando sono disconnessi, arrestati o trasferiti. di distanza.
Disattiva l'interfaccia utente predefinita
Se il DPC fornisce un'interfaccia utente per gestire gli utenti, puoi disattivare
un'interfaccia multiutente. Puoi farlo chiamando
DevicePolicyManager.setLogoutEnabled()
e l'aggiunta del parametro
DISALLOW_USER_SWITCH
come mostrato in
nell'esempio seguente:
Kotlin
// Explicitly disallow logging out using Android UI (disabled by default). dpm.setLogoutEnabled(adminName, false) // Disallow switching users in Android's UI. This DPC can still // call switchUser() to manage users. dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH)
Java
// Explicitly disallow logging out using Android UI (disabled by default). dpm.setLogoutEnabled(adminName, false); // Disallow switching users in Android's UI. This DPC can still // call switchUser() to manage users. dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH);
La persona che utilizza il dispositivo non può aggiungere utenti secondari con l'UI integrata di Android
poiché gli amministratori dei dispositivi completamente gestiti aggiungono automaticamente
Limitazione utente DISALLOW_ADD_USER
.
Messaggi di sessione
Quando la persona che utilizza un dispositivo passa a un nuovo utente, Android mostra un riquadro per evidenzia l'opzione. Android mostra i seguenti messaggi:
- Messaggio di avvio della sessione utente mostrato quando il dispositivo passa a una sessione secondaria dell'utente principale.
- Messaggio di sessione utente finale mostrato quando il dispositivo torna all'utente principale. di un utente secondario.
Il sistema non mostra i messaggi quando si passa da un utente secondario all'altro.
Poiché i messaggi potrebbero non essere adatti a tutte le situazioni, puoi cambiare il testo di questi messaggi. Ad esempio, se la tua soluzione utilizza un utente temporaneo sessioni, puoi segnalarlo nei messaggi, come: Arrestare il browser sessione e eliminazione dei dati personali in corso...
Il sistema mostra il messaggio solo per un paio di secondi, quindi ogni messaggio
deve essere una frase breve e chiara. Per personalizzare i messaggi, l'amministratore può chiamare
i metodi DevicePolicyManager
setStartUserSessionMessage()
e
setEndUserSessionMessage()
come mostrato in
nell'esempio seguente:
Kotlin
// Short, easy-to-read messages shown at the start and end of a session. // In your app, store these strings in a localizable resource. internal val START_USER_SESSION_MESSAGE = "Starting guest session…" internal val END_USER_SESSION_MESSAGE = "Stopping & clearing data…" // ... dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE) dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE)
Java
// Short, easy-to-read messages shown at the start and end of a session. // In your app, store these strings in a localizable resource. private static final String START_USER_SESSION_MESSAGE = "Starting guest session…"; private static final String END_USER_SESSION_MESSAGE = "Stopping & clearing data…"; // ... dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE); dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE);
Passa null
per eliminare i tuoi messaggi personalizzati e tornare alle impostazioni predefinite di Android
messaggi. Per controllare il testo attuale del messaggio, chiama
getStartUserSessionMessage()
oppure
getEndUserSessionMessage()
.
Il DPC deve impostare messaggi localizzati per le impostazioni internazionali correnti dell'utente. Devi anche aggiornare i messaggi quando modifiche alle impostazioni internazionali dell'utente:
Kotlin
override fun onReceive(context: Context?, intent: Intent?) { // Added the <action android:name="android.intent.action.LOCALE_CHANGED" /> // intent filter for our DeviceAdminReceiver subclass in the app manifest file. if (intent?.action === ACTION_LOCALE_CHANGED) { // Android's resources return a string suitable for the new locale. getManager(context).setStartUserSessionMessage( getWho(context), context?.getString(R.string.start_user_session_message)) getManager(context).setEndUserSessionMessage( getWho(context), context?.getString(R.string.end_user_session_message)) } super.onReceive(context, intent) }
Java
public void onReceive(Context context, Intent intent) { // Added the <action android:name="android.intent.action.LOCALE_CHANGED" /> // intent filter for our DeviceAdminReceiver subclass in the app manifest file. if (intent.getAction().equals(ACTION_LOCALE_CHANGED)) { // Android's resources return a string suitable for the new locale. getManager(context).setStartUserSessionMessage( getWho(context), context.getString(R.string.start_user_session_message)); getManager(context).setEndUserSessionMessage( getWho(context), context.getString(R.string.end_user_session_message)); } super.onReceive(context, intent); }
Coordinamento DPC (controller criteri dispositivi)
Per la gestione degli utenti secondari, in genere sono necessarie due istanze del DPC (controller criteri dispositivi), una delle quali il dispositivo completamente gestito, mentre l'altro è proprietario dell'utente secondario. Durante la creazione un nuovo utente, l'amministratore del dispositivo completamente gestito imposta un'altra istanza come amministratore del nuovo utente.
Utenti affiliati
Alcune API in questa guida per gli sviluppatori funzionano solo quando gli utenti secondari sono affiliati. Perché Android disattiva alcune funzionalità (ad esempio il logging di rete) quando aggiungi nuovi utenti secondari non affiliati il dispositivo, dovresti affiliare gli utenti appena possibile. Vedi l'esempio in Configurazione qui sotto.
Configura
Configura i nuovi utenti secondari (dal DPC proprietario dell'utente secondario) prima
per consentire agli utenti di utilizzarli. Puoi eseguire questa configurazione
DeviceAdminReceiver.onEnabled()
. Se in precedenza
imposta gli eventuali extra amministrativi della chiamata su createAndManageUser()
, puoi ottenere
dall'argomento intent
. L'esempio seguente mostra un'affiliazione DPC (controller criteri dispositivi)
un nuovo utente secondario nel callback:
Kotlin
override fun onEnabled(context: Context?, intent: Intent?) { super.onEnabled(context, intent) // Get the affiliation ID (our DPC previously put in the extras) and // set the ID for this new secondary user. intent?.getStringExtra(AFFILIATION_ID_KEY)?.let { val dpm = getManager(context) dpm.setAffiliationIds(getWho(context), setOf(it)) } // Continue setup of the new secondary user ... }
Java
public void onEnabled(Context context, Intent intent) { // Get the affiliation ID (our DPC previously put in the extras) and // set the ID for this new secondary user. String affiliationId = intent.getStringExtra(AFFILIATION_ID_KEY); if (affiliationId != null) { DevicePolicyManager dpm = getManager(context); dpm.setAffiliationIds(getWho(context), new HashSet<String>(Arrays.asList(affiliationId))); } // Continue setup of the new secondary user ... }
RPC tra DPC (controller criteri dispositivi)
Anche se le due istanze DPC vengono eseguite su utenti separati,
proprietari del dispositivo e gli utenti secondari possono comunicare tra loro.
Poiché la chiamata a un servizio di un altro DPC supera i confini dell'utente, il DPC non può
chiama bindService()
come normalmente
Android. Per l'associazione a un servizio in esecuzione in
un altro utente, richiama
DevicePolicyManager.bindDeviceAdminServiceAsUser()
Il DPC può essere associato solo ai servizi in esecuzione negli utenti restituiti
DevicePolicyManager.getBindDeviceAdminTargetUsers()
L'esempio seguente mostra l'amministratore di un'associazione utente secondaria all'amministratore
del dispositivo completamente gestito:
Kotlin
// From a secondary user, the list contains just the primary user. dpm.getBindDeviceAdminTargetUsers(adminName).forEach { // Set up the callbacks for the service connection. val intent = Intent(mContext, FullyManagedDeviceService::class.java) val serviceconnection = object : ServiceConnection { override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) { // Call methods on service ... } override fun onServiceDisconnected(componentName: ComponentName) { // Clean up or reconnect if needed ... } } // Bind to the service as the primary user [it]. val bindSuccessful = dpm.bindDeviceAdminServiceAsUser(adminName, intent, serviceconnection, Context.BIND_AUTO_CREATE, it) }
Java
// From a secondary user, the list contains just the primary user. List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(adminName); if (targetUsers.isEmpty()) { // If the users aren't affiliated, the list doesn't contain any users. return; } // Set up the callbacks for the service connection. Intent intent = new Intent(mContext, FullyManagedDeviceService.class); ServiceConnection serviceconnection = new ServiceConnection() { @Override public void onServiceConnected( ComponentName componentName, IBinder iBinder) { // Call methods on service ... } @Override public void onServiceDisconnected(ComponentName componentName) { // Clean up or reconnect if needed ... } }; // Bind to the service as the primary user. UserHandle primaryUser = targetUsers.get(0); boolean bindSuccessful = dpm.bindDeviceAdminServiceAsUser( adminName, intent, serviceconnection, Context.BIND_AUTO_CREATE, primaryUser);
Risorse aggiuntive
Per scoprire di più sui dispositivi dedicati, leggi i seguenti documenti:
- La panoramica dei dispositivi dedicati è una panoramica dispositivi dedicati.
- La modalità di blocco attività spiega come Bloccare un dispositivo dedicato a una singola app o un insieme di app.
- Libro di ricette sui dispositivi dedicati con ulteriori esempi per limitare i dispositivi dedicati e migliorare l'esperienza utente un'esperienza senza intervento manuale.