La función de roles de la aplicación permite que un administrador de TI otorgue privilegios especiales a una aplicación administrada en un dispositivo con Android. Si se asigna un rol específico, una app puede quedar exenta de las restricciones de energía y en segundo plano, la suspensión, la hibernación (en Android 14 y versiones posteriores) y tener inhabilitados los controles del usuario (es decir, incluye acciones del usuario, como forzar detención y borrar los datos de app) (en Android 11 y versiones posteriores), lo que le permite realizar su función crítica sin interrupciones. Además, la app puede recibir notificaciones sobre sus roles asignados, lo que le permite iniciarse sin la intervención del usuario.
Para obtener una lista de los roles de aplicación disponibles y los privilegios especiales otorgados a
cada rol, consulta RoleType.
Requisitos previos
El dispositivo se administra con un EMM basado en la AMAPI (no se admiten los EMM que usan un DPC personalizado).
Prepara tu app para usar la función
La integración con el SDK de AMAPI solo es necesaria si la app quiere recibir notificaciones de sus roles asignados, lo que le permite iniciarse por sí misma (es decir, iniciarse automáticamente sin interacción del usuario).
Integra el SDK de AMAPI en tu app
Puedes encontrar más información sobre el SDK de AMAPI y cómo agregarlo a tu app en la guía de integración del SDK de AMAPI.
Agrega los metadatos obligatorios al manifiesto de la app
Android Device Policy (ADP) necesita conocer el ComponentName de tu clase
que implementa NotificationReceiverService para notificar a tu app sobre sus
roles asignados. Debes etiquetar tu servicio en AndroidManifest.xml de forma adecuada para
que ADP pueda descubrirlo automáticamente.
- Tu app debe tener exactamente un servicio que sea
enabledy tengameta-dataconandroid:nameigual acom.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES - Este servicio debe tener
android:exportedconfigurado comotrue - El
android:valuedemeta-datadebe establecerse en una cadena vacía
<service
android:name=".MyNotificationReceiverService"
android:exported="true">
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES" android:value="" />
</service>
Si estás probando el rol COMPANION_APP, también debes agregar el siguiente
meta-data a tu servicio para que Android Device Policy pueda enviar actualizaciones de estado de comandos locales
a tu app:
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_COMMAND_STATUS" android:value="" />
Crea un servicio que extienda NotificationReceiverService (o actualiza el existente)
Crea o actualiza tu NotificationReceiverService existente y, luego, implementa un AppRolesListener para escuchar los roles asignados a tu app. Solo se requiere getAppRolesListener() para escuchar los roles asignados a tu app. Si se le asigna un rol de COMPANION_APP a tu app, también debes implementar 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"
}
}
Tu app puede recibir notificaciones varias veces si sus roles cambian varias veces. Si
se quitan todos los roles, tu app recibirá una notificación con una lista vacía de
roles. Esta notificación sacará a tu app del estado detenido y, junto con las exenciones otorgadas para tu app, esta podrá iniciarse sin interacción del usuario. Gracias a las notificaciones y exenciones de roles de la app, esta puede escuchar las transmisiones de ACTION_BOOT_COMPLETED. Si tu app depende de
sus parámetros de configuración administrados para iniciarse, consulta
Cómo establecer parámetros de configuración administrados para obtener información sobre cómo leer y escuchar
los cambios.
A partir del SDK de AMAPI 1.9.0, cada rol en AppRolesSetRequest también incluye el Role.ExtraCapabilities que el administrador de TI otorgó en la política. Por ejemplo, una app complementaria puede verificar si tiene permiso para emitir un comando de limpieza local:
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 el administrador de TI puede otorgar funciones adicionales. Si configuras extraCapabilities
en un rol que pasas a EnvironmentClient, la llamada falla con un
InvalidArgumentException.
Aprovisiona el dispositivo con políticas de roles de apps
Los desarrolladores de apps pueden probar la asignación de roles de app a su aplicación con una EMM o siguiendo la guía de inicio rápido de la API de Android Management. El notebook de Colab de AMAPI te permite inscribir una empresa, crear una política y aprovisionar un dispositivo.
Establece la política para tu app con roles de app
Configura un policy con los roles de la app que se espera que tenga tu app con
ApplicationPolicy.roles.
En el siguiente ejemplo, se muestra cómo configurar el rol para las apps de MTD:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
Solo el rol COMPANION_APP admite
extraCapabilities. Para permitir que la app complementaria
borre el dispositivo o el perfil de trabajo de forma local, establece
extraCapabilities.localDeviceWipeCommand en
LOCAL_DEVICE_WIPE_COMMAND_ALLOWED para ese rol.
Antes de asignar los roles como se especifica en la política, el sistema verificará que
la huella digital del certificado de la clave de firma de la app en el dispositivo coincida con la de
Play Store.
Si la huella digital es diferente, los roles no se asignarán a la
app y se informará el incumplimiento de NonComplianceReason.APP_SIGNING_CERT_MISMATCH
al EMM.
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"signingKeyCerts": [
{ "signingKeyCertFingerprintSha256": "base64-encoded-sha256" }
],
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
Si tu app tiene una configuración administrada, el administrador de TI puede establecer una configuración inicial para los restriction pertinentes en la política de la aplicación:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
],
"managedConfiguration": {
"<key>": "<value>"
}
}
]
}
Verifica el estado de la exención de batería
Las apps con el rol de defensa contra amenazas para dispositivos móviles (MTD) están exentas automáticamente de las restricciones de energía en segundo plano estándar. Sin embargo, esta exención la implementa el intervalo de App Standby, en lugar de la lista de entidades permitidas de energía del sistema.
Para verificar si la exención de la app está activa, sigue estos pasos:
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