La funzionalità dei ruoli delle applicazioni consente a un amministratore IT di concedere privilegi speciali a un'applicazione gestita su un dispositivo Android. Assegnando un ruolo specifico, un'app può essere esentata dalle limitazioni di alimentazione e in background, dalla sospensione, dall'ibernazione (su Android 14 e versioni successive) e dalla disattivazione dei controlli utente (ovvero include azioni utente come l'interruzione forzata e la cancellazione dei dati dell'app) (su Android 11 e versioni successive), consentendole di svolgere la sua funzione critica senza interruzioni. Inoltre, l'app può ricevere notifiche sui ruoli assegnati, il che le consente di avviarsi autonomamente senza l'intervento dell'utente.
Per un elenco dei ruoli dell'applicazione disponibili e dei privilegi speciali concessi a ciascun ruolo, consulta RoleType.
Prerequisiti
Il dispositivo è gestito da un EMM basato su AMAPI (gli EMM che utilizzano un DPC personalizzato non sono supportati).
Prepara l'app per l'utilizzo della funzionalità
L'integrazione con l'SDK AMAPI è necessaria solo se l'app vuole ricevere notifiche dei ruoli assegnati, il che le consente di avviarsi autonomamente (ovvero di avviarsi automaticamente senza l'interazione dell'utente).
Integra l'SDK AMAPI nella tua app
Puoi trovare ulteriori informazioni sull'SDK AMAPI e su come aggiungerlo alla tua app nella guida all'integrazione dell'SDK AMAPI.
Aggiungi i metadati richiesti al manifest dell'app
Android Device Policy (ADP) deve conoscere il ComponentName della tua classe
che implementa NotificationReceiverService per notificare alla tua app i
ruoli assegnati. Devi taggare il tuo servizio in AndroidManifest.xml in modo che possa essere rilevato automaticamente da ADP.
- La tua app deve avere esattamente un servizio che è
enablede hameta-dataconandroid:nameuguale acom.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES - Questo servizio deve avere
android:exportedimpostato sutrue - Il campo
android:valuedimeta-datadeve essere impostato su una stringa vuota
<service
android:name=".MyNotificationReceiverService"
android:exported="true">
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES" android:value="" />
</service>
Se stai testando il ruolo COMPANION_APP, devi anche aggiungere il seguente meta-data al tuo servizio in modo che Android Device Policy possa inviare aggiornamenti di stato dei comandi locali alla tua app:
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_COMMAND_STATUS" android:value="" />
Crea un servizio che estende NotificationReceiverService (o aggiorna quello esistente)
Crea o aggiorna il tuo NotificationReceiverService esistente e implementa un
AppRolesListener per ascoltare i ruoli assegnati alla tua app. Solo
getAppRolesListener() è necessario per ascoltare i ruoli assegnati alla tua
app. Se alla tua app viene assegnato un ruolo COMPANION_APP, devi anche implementare
getCommandListener():
import android.util.Log
import com.google.android.managementapi.approles.AppRolesListener
import com.google.android.managementapi.approles.model.AppRolesSetRequest
import com.google.android.managementapi.approles.model.AppRolesSetResponse
import com.google.android.managementapi.commands.CommandListener
import com.google.android.managementapi.commands.model.Command
import com.google.android.managementapi.notification.NotificationReceiverService
class MyNotificationReceiverService : NotificationReceiverService() {
// If your app wants to listen for roles assigned
override fun getAppRolesListener(): AppRolesListener =
object : AppRolesListener {
override fun onAppRolesSet(request: AppRolesSetRequest): AppRolesSetResponse {
val roleTypes = request.roles.map { role -> role.roleType }
Log.i(TAG, "onAppRolesSet: $roleTypes")
return AppRolesSetResponse.getDefaultInstance()
}
}
// If your app wants to listen for local command status updates
// Only relevant for COMPANION_APP role
override fun getCommandListener(): CommandListener {
return object : CommandListener {
override fun onCommandStatusChanged(command: Command) {
Log.i(TAG, "onCommandStatusChanged")
}
}
}
private companion object {
const val TAG = "MyNotificationReceiverService"
}
}
La tua app può ricevere notifiche più volte se i suoi ruoli cambiano più volte. Se
vengono rimossi tutti i ruoli, la tua app riceverà comunque una notifica con un elenco vuoto di
ruoli. Questa notifica farà uscire l'app dallo stato di arresto e, insieme alle esenzioni concesse per l'app, l'app potrà avviarsi autonomamente senza alcuna interazione dell'utente. Grazie alla notifica e alle esenzioni dei ruoli dell'app, la tua app può ascoltare le trasmissioni ACTION_BOOT_COMPLETED. Se la tua app dipende dalle sue configurazioni gestite per l'avvio automatico, consulta Configura le configurazioni gestite per scoprire come leggere e ascoltare le modifiche.
A partire dall'SDK AMAPI 1.9.0, ogni ruolo in
AppRolesSetRequest include anche Role.ExtraCapabilities che l'amministratore IT
ha concesso nella policy. Ad esempio, un'app complementare può verificare se è autorizzata a inviare un comando di cancellazione locale:
import com.google.android.managementapi.approles.model.AppRolesSetRequest
import com.google.android.managementapi.approles.model.AppRolesSetResponse
import com.google.android.managementapi.common.model.Role
...
override fun onAppRolesSet(request: AppRolesSetRequest): AppRolesSetResponse {
val canWipeLocally =
request.roles.any { role ->
role.roleType == Role.RoleType.COMPANION_APP &&
role.extraCapabilities.localDeviceWipeCommand ==
Role.ExtraCapabilities.LocalDeviceWipeCommand.LOCAL_DEVICE_WIPE_COMMAND_ALLOWED
}
Log.i(TAG, "onAppRolesSet: canWipeLocally=$canWipeLocally")
return AppRolesSetResponse.getDefaultInstance()
}
Solo l'amministratore IT può concedere funzionalità aggiuntive. Se imposti extraCapabilities su un ruolo che passi a EnvironmentClient, la chiamata non va a buon fine e viene visualizzato un InvalidArgumentException.
Esegui il provisioning del dispositivo con i criteri dei ruoli delle app
Gli sviluppatori di app possono testare l'assegnazione dei ruoli app alla propria applicazione utilizzando un EMM o seguendo la guida rapida all'API Android Management. Il notebook di Colab AMAPI ti consente di registrare un'azienda, creare una policy ed eseguire il provisioning di un dispositivo.
Imposta la policy per la tua app con i ruoli dell'app
Configura un policy con i ruoli dell'app che la tua app deve avere utilizzando
ApplicationPolicy.roles.
L'esempio seguente mostra come configurare il ruolo per le app MTD:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
Solo il ruolo COMPANION_APP supporta extraCapabilities. Per consentire all'app complementare di cancellare i dati del dispositivo o del profilo di lavoro localmente, imposta extraCapabilities.localDeviceWipeCommand su LOCAL_DEVICE_WIPE_COMMAND_ALLOWED per quel ruolo.
Prima di assegnare i ruoli come specificato nella policy, il sistema verificherà che
il fingerprint del certificato della chiave di firma dell'app sul dispositivo corrisponda a quello del
Play Store.
Se l'impronta è diversa, i ruoli non verranno assegnati all'app e la non conformità di NonComplianceReason.APP_SIGNING_CERT_MISMATCH verrà segnalata all'EMM.
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"signingKeyCerts": [
{ "signingKeyCertFingerprintSha256": "base64-encoded-sha256" }
],
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
Se la tua app ha una configurazione gestita, l'amministratore IT può impostare una configurazione iniziale per i restriction pertinenti nella policy dell'applicazione:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
],
"managedConfiguration": {
"<key>": "<value>"
}
}
]
}
Verifica lo stato di esenzione della batteria
Le app con il ruolo Mobile Threat Defense (MTD) sono automaticamente esenti dalle limitazioni standard per il consumo energetico in background. Tuttavia, questa esenzione viene implementata dal bucket di standby delle app anziché dalla lista consentita di alimentazione del sistema.
Per verificare se l'esenzione dell'app è attiva:
import android.app.usage.UsageStatsManager
import android.content.Context
// UsageStatsManager.STANDBY_BUCKET_EXEMPTED is annotated as a @SystemApi. We can redefine it for clarity.
// Define this at the top level of your file, or inside a companion object
private const val STANDBY_BUCKET_EXEMPTED = 5
private fun isAppExemptedFromAppStandbyBucket(): Boolean =
(getSystemService(Context.USAGE_STATS_SERVICE) as? UsageStatsManager)
?.appStandbyBucket == STANDBY_BUCKET_EXEMPTED