管理应用角色

借助应用角色功能,IT 管理员可以向 Android 设备上的受管理应用授予特殊权限。通过分配特定角色,应用可以免受电源和后台限制、暂停、休眠(在 Android 14 及更高版本中)的影响,并且可以停用用户控件(即包括强制停止和清除应用数据等用户操作)(在 Android 11 及更高版本中),从而使其能够不受中断地执行关键功能。此外,应用可以收到有关其分配角色的通知,从而在无需用户干预的情况下自行启动。

前提条件

设备由基于 AMAPI 的 EMM 管理(不支持使用自定义 DPC 的 EMM)。

准备应用以使用该功能

仅当应用希望收到有关其分配角色的通知,从而能够自行启动(即在没有用户互动的情况下自动启动)时,才需要与 AMAPI SDK 集成。

在应用中与 AMAPI SDK 集成

如需详细了解 AMAPI SDK 以及如何将其添加到应用中,请参阅 AMAPI SDK 集成指南

向应用的清单添加所需的元数据

Android Device Policy (ADP) 需要知道实现 NotificationReceiverService 的类的 ComponentName,以便将分配的角色通知给您的应用。您必须在 AndroidManifest.xml 中适当标记服务,以便 ADP 自动发现该服务。

  • 您的应用必须只有一个 enabled 服务,该服务具有 meta-data,且 android:name 等于 com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES
  • 此服务的 android:exported 必须设置为 true
  • meta-dataandroid:value 必须设置为空字符串
<service
 android:name=".MyNotificationReceiverService"
 android:exported="true">
    <meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES" android:value="" />
</service>

如果您要测试 COMPANION_APP 角色,还应向服务添加以下 meta-data,以便 Android Device Policy 可以向您的应用发送本地命令状态更新:

<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_COMMAND_STATUS" android:value="" />

创建扩展 NotificationReceiverService 的服务(或更新现有服务)

创建或更新现有 NotificationReceiverService 并实现 AppRolesListener 以侦听分配给应用的的角色。侦听分配给应用的的角色时,只需要 getAppRolesListener()。如果应用被分配了 COMPANION_APP 角色,您还应实现 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"
  }
}

如果应用的角色多次发生变化,则可以多次收到通知。如果移除了所有角色,您的应用仍会收到通知,但角色列表为空。此通知将使您的应用脱离停止状态,并且在授予应用的豁免权限的支持下,您的应用可以在没有任何用户互动的情况下自行启动。借助应用角色通知和豁免,您的应用可以监听 ACTION_BOOT_COMPLETED 广播。如果您的应用依赖于其托管配置来启动自身,请参阅设置托管配置,了解如何读取和监听更改。

为设备配置应用角色政策

应用开发者可以使用 EMM 或按照 Android Management API 快速入门指南测试为其应用分配应用角色。借助 AMAPI Colab 笔记本,您可以注册企业、创建政策和配置设备。

使用应用角色为应用设置政策

使用 ApplicationPolicy.roles 设置具有应用预期角色的 policy

以下示例展示了如何为 MTD 应用配置角色:

{
  "applications": [

    {
      "packageName": "com.example.mtd",
      "installType": "FORCE_INSTALLED",
      "roles": [
        { "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
      ]
    }
  ]
}

在按照政策指定的方式分配角色之前,系统会检查设备上应用的签名密钥证书指纹是否与 Play 商店中的指纹一致。如果指纹不同,则不会将角色分配给应用,并且系统会向 EMM 报告 NonComplianceReason.APP_SIGNING_CERT_MISMATCH 不合规。

{
  "applications": [

    {
      "packageName": "com.example.mtd",
      "installType": "FORCE_INSTALLED",
      "signingKeyCerts": [
         { "signingKeyCertFingerprintSha256": "base64-encoded-sha256" }
       ],
      "roles": [
        { "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
      ]
    }
  ]
}

如果您的应用具有托管配置,IT 管理员可以在应用政策中为相关 restriction 设置初始配置:

{
  "applications": [

    {
      "packageName": "com.example.mtd",
      "installType": "FORCE_INSTALLED",
      "roles": [
        { "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
      ],
      "managedConfiguration": {
        "<key>": "<value>"
      }
    }
  ]
}