构建设备政策控制器

本指南介绍如何为 Android 企业部署中的设备开发设备政策控制器 (DPC)。DPC 应用(以前称为工作政策控制器)控制设备上的本地设备政策和系统应用。

关于 DPC

在 Android 企业部署中,企业可以控制用户设备的各个方面,例如将工作相关信息与用户的个人数据隔离、预配置环境中批准的应用,或禁用设备功能(例如摄像头)。

作为 EMM,您可以开发一个 DPC 应用,供您的客户与您的 EMM 控制台和服务器结合使用。您的客户将 DPC 部署到他们管理的设备上。DPC 充当您的 EMM 控制台(和服务器)与设备之间的桥梁。管理员使用 EMM 控制台执行一系列任务,包括配置设备设置和应用。

DPC 在其安装的设备上创建和管理工作资料。工作资料加密工作相关信息,并将其与用户的个人应用和数据分开。在创建工作资料之前,DPC 还可以为设备配置一个托管式 Google Play 账号。

本指南向您展示如何开发一个可以创建和管理工作资料的 DPC。

适用于 EMM 的 DPC 支持库

适用于 EMM 的 DPC 支持库包含实用程序和辅助类,可帮助在企业环境中配置和管理 Android 设备。该库允许您在 DPC 应用中利用重要功能。

  • 托管式 Google Play 账号配置支持:从 DPC 应用配置托管式 Google Play 账号要求 Google Play 和 Google Play 服务应用满足最低版本要求。然而,更新这些应用可能很复杂。DPC 支持库负责更新这些应用,并确保与托管式 Google Play 账号配置过程的未来更新兼容。有关详细信息,请参阅托管式 Google Play 账号配置支持
  • 托管配置支持:使用 Play EMM API 处理已批准应用的托管配置是 DPC 上实现托管配置的最简单方法。DPC 支持库允许您将应用管理配置(以前称为应用限制)的设置任务委派给 Google Play,这些设置由管理员使用您的 EMM 控制台设置。使用 Play EMM API 处理托管配置允许在安装过程中原子地应用应用配置。有关如何在 DPC 中启用此功能的更多信息,请参阅将托管配置应用于工作应用

按照以下步骤下载库。本指南中详细介绍的任务假设使用 DPC 支持库。

下载 DPC 支持库

要使用 DPC 支持库,请从Android Enterprise EMM Provider 社区下载该库。在构建 DPC 应用时,您必须将该库添加到您的 build.gradle 文件并处理其他依赖项。例如,该库需要 11.4.0 版的 Google Play Services 认证客户端库

  1. 将库添加到 build.gradle 文件

    Groovy

    implementation(name:'dpcsupport-yyyymmdd', ext:'aar')

    Kotlin

    implementation(name = "dpcsupport-yyyymmdd", ext = "aar")
  2. 将 11.4.0 版的 Google Play 服务认证客户端库添加到 build.gradle 文件

    Groovy

    implementation 'com.google.android.gms:play-services-auth:11.4.0'

    Kotlin

    implementation("com.google.android.gms:play-services-auth:11.4.0")

该库运行需要某些权限,因此您在上传到 Google Play 时必须将这些权限添加到 DPC 应用的清单中

  <uses-permission android:name=
      "android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
  <uses-permission android:name=
      "android.permission.GET_ACCOUNTS"/>
  <uses-permission android:name=
      "android.permission.MANAGE_ACCOUNTS"/>
  <uses-permission android:name=
      "android.permission.WRITE_SYNC_SETTINGS"/>
  <uses-permission android:name=
      "com.google.android.providers.gsf.permission.READ_GSERVICES"/>

除了这些初步设置和部署步骤之外,您还必须根据要实现的功能,在 DPC 代码中初始化特定的库功能。详细信息包含在下面的相关部分中。

创建 DPC

基于现有的设备管理应用程序模型构建您的 DPC。具体来说,您的应用必须像设备管理中描述的那样,子类化 DeviceAdminReceiverandroid.app.admin 包中的一个类)。

创建工作资料

有关如何创建基本工作资料的示例,请参阅 GitHub 上的BasicManagedProfile

要在已存在个人资料的设备上创建工作资料,请首先检查设备是否支持工作资料,方法是检查是否存在 FEATURE_MANAGED_USERS 系统功能

Kotlin

if (!packageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)) {
    // This device does not support work profiles!
}

Java

PackageManager pm = getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)) {
    // This device does not support work profiles!
}

如果设备支持工作资料,请通过发送带有 ACTION_PROVISION_MANAGED_PROFILE 操作的 Intent 来创建工作资料。(在某些文档中,在 Android 企业环境中,托管资料是一个通用术语,与工作资料含义相同。)将设备管理员包名作为额外信息包含在内

Kotlin

val provisioningActivity = getActivity()

// You'll need the package name for the DPC app.
val myDPCPackageName = "com.example.myDPCApp"

// Set up the provisioning intent
val adminComponent = ComponentName(provisioningActivity.applicationContext, MyAdminReceiver::class.java)
provisioningIntent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, adminComponent.flattenToString())
if (provisioningIntent.resolveActivity(provisioningActivity.packageManager) == null) {
    // No handler for intent! Can't provision this device.
    // Show an error message and cancel.
} else {
    // REQUEST_PROVISION_MANAGED_PROFILE is defined
    // to be a suitable request code
    startActivityForResult(provisioningIntent,
            REQUEST_PROVISION_MANAGED_PROFILE)
    provisioningActivity.finish()
}

Java

Activity provisioningActivity = getActivity();
// You'll need the package name for the DPC app.
String myDPCPackageName = "com.example.myDPCApp";
// Set up the provisioning intent
Intent provisioningIntent =
        new Intent("android.app.action.PROVISION_MANAGED_PROFILE");
ComponentName adminComponent = new ComponentName(provisioningActivity.getApplicationContext(), MyAdminReceiver.class);
provisioningIntent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, adminComponent.flattenToString());
if (provisioningIntent.resolveActivity(provisioningActivity.getPackageManager())
         == null) {
    // No handler for intent! Can't provision this device.
    // Show an error message and cancel.
} else {
    // REQUEST_PROVISION_MANAGED_PROFILE is defined
    // to be a suitable request code
    startActivityForResult(provisioningIntent,
            REQUEST_PROVISION_MANAGED_PROFILE);
    provisioningActivity.finish();
}

系统通过执行以下操作响应此 Intent:

  • 验证设备是否已加密。如果未加密,系统会提示用户在继续之前加密设备。
  • 创建工作资料。
  • 从工作资料中删除非必需应用。
  • 将 DPC 应用复制到工作资料中,并将 DPC 本身设置为资料所有者。

覆盖 onActivityResult() 以查看配置是否成功

Kotlin

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    // Check if this is the result of the provisioning activity
    if (requestCode == REQUEST_PROVISION_MANAGED_PROFILE) {
        // If provisioning was successful, the result code is
        // Activity.RESULT_OK
        if (resultCode == Activity.RESULT_OK) {
            // Work profile created and provisioned.
        } else {
            // Provisioning failed.
        }
        return
    } else {
        // This is the result of some other activity. Call the superclass.
        super.onActivityResult(requestCode, resultCode, data)
    }
}

Java

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Check if this is the result of the provisioning activity
    if (requestCode == REQUEST_PROVISION_MANAGED_PROFILE) {
        // If provisioning was successful, the result code is
        // Activity.RESULT_OK
        if (resultCode == Activity.RESULT_OK) {
            // Work profile created and provisioned.
        } else {
            // Provisioning failed.
        }
        return;
    } else {
        // This is the result of some other activity. Call the superclass.
        super.onActivityResult(requestCode, resultCode, data);
    }
}

完成工作资料的启用

资料配置完成后,系统会调用 DPC 应用的 DeviceAdminReceiver.onProfileProvisioningComplete() 方法。覆盖此回调方法以完成工作资料的启用。

典型的 DeviceAdminReceiver.onProfileProvisioningComplete() 回调实现会执行以下操作:

激活工作资料

完成这些任务后,调用设备政策管理器的 setProfileEnabled() 方法以激活工作资料

Kotlin

// Get the device policy manager
val myDevicePolicyMgr = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val componentName = myDeviceAdminReceiver.getComponentName(this)
// Set the name for the newly created work profile.
myDevicePolicyMgr.setProfileName(componentName, "My New Work Profile")
// ...and enable the profile
myDevicePolicyMgr.setProfileEnabled(componentName)

Java

// Get the device policy manager
DevicePolicyManager myDevicePolicyMgr =
        (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName componentName = myDeviceAdminReceiver.getComponentName(this);
// Set the name for the newly created work profile.
myDevicePolicyMgr.setProfileName(componentName, "My New Work Profile");
// ...and enable the profile
myDevicePolicyMgr.setProfileEnabled(componentName);

设置设备政策

DPC 应用根据管理员的设置应用设备政策,以满足组织的要求和限制。例如,安全政策可能要求设备在密码尝试失败一定次数后锁定。DPC 查询 EMM 控制台以获取当前政策,然后使用设备管理 API 应用政策。

有关如何应用设备政策的信息,请参阅政策

将托管配置应用于工作应用

托管配置让您可以为客户提供预配置已批准部署的应用的能力,并在配置需要更改时轻松更新这些应用。在部署前配置应用可确保在目标设备上安装应用时满足组织的安全和其他政策。

应用功能由应用开发者在 XML 架构(托管配置架构)中定义,该架构在应用上传到 Google Play 时随附(应用开发者,有关详细信息,请参阅设置托管配置)。

您从应用中检索此架构,以便在 EMM 控制台中向您的客户管理员显示,提供一个用户界面,其中显示架构中定义的各种选项,并使管理员能够预配置应用设置。管理员设置的最终托管配置通常存储在 EMM 服务器上,然后服务器使用 Play EMM API 设置 ManagedconfigurationsfordeviceManagedconfigurationsforuser。有关详细信息,请参阅通过 Play 进行托管配置

托管配置可以通过 Play EMM API(推荐方法)或直接从 DPC 应用(在直接从 DPC 应用托管配置中描述)应用。使用 Play EMM API 有几个优点,包括易于实现,因为您可以使用 DPC 支持库来简化 DPC 任务。此外,Play EMM API

  • 在新应用安装时原子地设置配置,从而确保用户首次启动应用时即可使用。
  • 允许您按用户管理配置,因此您可以避免按设备监控配置。

使用 Play EMM API 应用托管配置

要将 Play EMM API 用于托管配置,DPC 必须允许 Google Play 设置配置。DPC 支持库通过代理 Google Play 发送的配置来为您处理此任务。

要使用 Play EMM API,请下载 DPC 支持库,然后在 DPC 中启用托管配置支持。

在 DPC 中启用托管配置支持

在 DPC 中导入此类别

com.google.android.apps.work.dpcsupport.ManagedConfigurationsSupport

初始化托管配置库。在此示例中,“admin”是 DeviceAdminReceiver 的 ComponentName。

Kotlin

var managedConfigurationsSupport = ManagedConfigurationsSupport(context, admin)

Java

ManagedConfigurationsSupport managedConfigurationsSupport =
    new ManagedConfigurationsSupport(context, admin);

启用托管配置

Kotlin

managedConfigurationsSupport.enableManagedConfigurations()

Java

managedConfigurationsSupport.enableManagedConfigurations();

在 DPC 中初始化此库后,您可以在 EMM 控制台和服务器中使用 Google Play EMM API 将托管配置应用于已批准的应用,而无需直接在 DPC 中编写这些任务。有关详细信息,请参阅通过 Play 进行托管配置

直接从 DPC 应用托管配置

要直接从 DPC 更改应用的配置设置,请调用 DevicePolicyManager.setApplicationRestrictions() 方法,并传入 DPC 应用的 DeviceAdminReceiver、目标应用的包名以及包含管理员设置的应用托管配置的 Bundle 的参数。有关详细信息,请参阅DPC 与 EMM 控制台如何交互设置托管配置。但是请注意,在托管式 Google Play 账号部署中不建议使用这种应用托管配置的替代方法。

托管式 Google Play 账号配置支持

DPC 支持库包含对配置托管式 Google Play 账号的支持。要使用此支持,您必须首先初始化该库,然后才能确保工作环境添加托管式 Google Play 账号

在 DPC 中初始化托管式 Google Play 账号支持

在 DPC 中导入此类别

com.google.android.apps.work.dpcsupport.AndroidForWorkAccountSupport

初始化配置兼容性库。在此示例中,“admin”是 DeviceAdminReceiverComponentName

Kotlin

var androidForWorkAccountSupport = AndroidForWorkAccountSupport(context, admin)

Java

AndroidForWorkAccountSupport androidForWorkAccountSupport =
    new AndroidForWorkAccountSupport(context, admin);

确保托管式 Google Play 账号的工作环境

DPC 以资料所有者模式 (ACTION_PROVISION_MANAGED_PROFILE) 或设备所有者模式 (ACTION_PROVISION_MANAGED_DEVICE) 配置设备后,请通过调用以下方法确保设备支持托管式 Google Play 账号:

Kotlin

androidForWorkAccountSupport.ensureWorkingEnvironment(callback)

Java

androidForWorkAccountSupport.ensureWorkingEnvironment(callback);

回调报告此过程的成功或失败。当回调成功返回时,可以添加托管式 Google Play 账号。如果回调报告错误,请提示用户确保设备具有网络连接(例如,如果下载失败)。在其他情况下,请向 Google 报告失败。

Kotlin

object : WorkingEnvironmentCallback() {
    override fun onSuccess() {
        // Can now provision the managed Google Play Account
    }
    override fun onFailure(error: Error) {
        // Notify user, handle error (check network connection)
    }
}

Java

new WorkingEnvironmentCallback() {
    @Override
    public void onSuccess() {
        // Can now provision the managed Google Play Account
    }

    @Override
    public void onFailure(Error error) {
        // Notify user, handle error (check network connection)
    }
}

添加托管式 Google Play 账号

Android 框架的 AccountManager 可以向设备添加托管式 Google Play 账号。为了简化与 AccountManager 的交互,请使用 DPC 支持库中的辅助函数(示例如下)。该函数处理 Google Play 服务器返回的令牌,并促进托管式 Google Play 账号的配置。当托管式 Google Play 账号处于有效状态时,该函数返回

Kotlin

androidForWorkAccountSupport.addAndroidForWorkAccount(token, accountAddedCallback)

Java

androidForWorkAccountSupport.addAndroidForWorkAccount(token, accountAddedCallback);
  • token — 由 Google Play EMM API Users.generateAuthenticationToken() 调用生成的用于用户身份验证的令牌。
  • accountAddedCallback — 返回已成功添加到设备的托管式 Google Play 账号。此回调应包括 onAccountReady()onFailure() 方法。

Kotlin

val workAccountAddedCallback = object : WorkAccountAddedCallback() {
    override fun onAccountReady(account: Account, deviceHint: String) {
        // Device account was successfully added to the device
        // and is ready to be used.
    }

    override fun onFailure(error: Error) {
        // The account was not successfully added. Check that the token
        // provided was valid (it expires after a certain period of time).
    }
}

Java

WorkAccountAddedCallback workAccountAddedCallback =
    new WorkAccountAddedCallback() {
        @Override
        public void onAccountReady(Account account, String deviceHint) {
            // Device account was successfully added to the device
            // and is ready to be used.
        }

        @Override
        public void onFailure(Error error) {
            // The account was not successfully added. Check that the token
            // provided was valid (it expires after a certain period of time).
        }
};
  • 要了解有关设备管理 API 的更多信息,请参阅设备管理
  • 要了解 Android Enterprise 配置方法,请参阅 Android Enterprise 开发者指南中的配置设备
  • 有关演示如何创建基本工作资料的 GitHub 示例,请参阅BasicManagedProfile
  • 有关演示如何以资料所有者身份设置其他应用配置的 GitHub 示例,请参阅AppRestrictionEnforcer