Administra los roles de la aplicación

La función de roles de aplicación permite que un administrador de TI otorgue privilegios especiales a una aplicación administrada en un dispositivo con tecnología Android. Si se asigna un rol específico, se puede eximir una app de las restricciones de energía y de segundo plano, la suspensión, la hibernación (en Android 14 y versiones posteriores) y la inhabilitación de los controles del usuario (es decir, incluye acciones del usuario, como forzar detención de la app y borrar los datos de app) (en Android 11 y versiones posteriores), lo que le permite realizar su función fundamental sin interrupciones. Además, se puede notificar a la app sobre sus roles asignados, lo que le permite inicializarse sin intervención del usuario.

Para obtener una lista de los roles de aplicación disponibles y los privilegios especiales que se otorgan a cada rol, consulta RoleType.

Requisitos previos

El dispositivo está administrado por un EMM basado en AMAPI (no se admiten 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 sobre sus roles asignados, lo que le permite inicializarse (es decir, iniciar 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 requeridos 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 esté enabled y que tenga meta-data con android:name igual a com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES
  • Este servicio debe tener android:exported configurado como true.
  • El android:value de meta-data debe 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 los siguientes 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 detectar los roles asignados a tu app. Solo se requiere getAppRolesListener() para detectar los roles asignados a tu app. Si a tu app se le asigna un rol COMPANION_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"
  }
}

Se puede notificar a tu app varias veces si sus roles cambian varias veces. Si se quitan todos los roles, se le notificará a tu app con una lista de roles vacía. Esta notificación sacará a tu app del estado detenido y, junto con las exenciones otorgadas para tu app, esta podrá inicializarse sin ninguna interacción del usuario. Gracias a la notificación y las exenciones de los roles de la app, tu app puede detectar ACTION_BOOT_COMPLETED transmisiones. Si tu app depende de sus configuraciones administradas para inicializarse, consulta Cómo configurar las configuraciones administradas para obtener información sobre cómo leer y detectar cambios.

Aprovisiona el dispositivo con políticas de roles de aplicación

Los desarrolladores de apps pueden probar la asignación de roles de aplicación a su aplicación con un EMM o siguiendo la guía de inicio rápido de Android Management API. 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 aplicación

Configura un policy con los roles de aplicación que tu app debe tener con el 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" }
      ]
    }
  ]
}

Antes de asignar los roles según lo especificado 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 NonComplianceReason.APP_SIGNING_CERT_MISMATCH se informará al EMM sobre el incumplimiento.

{
  "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 configuración administrada, el administrador de TI puede configurar una configuración inicial para las restrictions 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 exención de la batería

Las apps con el rol de Mobile Threat Defense (MTD) están exentas automáticamente de las restricciones de energía en segundo plano estándar. Sin embargo, esta exención se implementa con el bucket 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, haz lo siguiente:

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