管理系统更新

本开发者指南介绍了设备政策控制器 (DPC) 可以如何 代表设备用户管理 Android 系统更新。

简介

Android 设备可以接收和安装系统的无线下载 (OTA) 更新 和应用程序软件Android 会通知设备用户系统更新 可用,且设备用户可以立即安装更新,也可以稍后安装。

IT 管理员可以使用您的 DPC 为设备用户管理系统更新。设备政策控制器 (DPC) 可以拥有全托管式设备(称为设备所有者),也可以拥有工作资料 (称为商家资料所有者)。表 1 显示了设备所有者如何管理系统 更新,而个人资料所有者只能报告系统更新的相关信息。

表 1:可供 DPC 执行的任务取决于所有者模式

任务 设备所有者 个人资料所有者
检查是否有待处理的系统更新
有新的系统更新可用时收到回调
设置本地更新政策以控制 Android 何时安装系统更新
在关键时间段内冻结操作系统版本

检查是否有待处理的更新

待处理的更新是指尚未安装的设备的系统更新。 设备政策控制器 (DPC) 可帮助 IT 管理员检查哪些设备有待处理的系统更新,以及 要求设备用户立即安装重要更新。

在 Android 8.0(API 级别 26)或更高版本上运行的设备所有者和资料所有者 可以检查设备是否有待处理的系统更新。致电 DevicePolicyManager.getPendingSystemUpdate() 如果设备是最新版本,则返回 null。如果系统更新在等待处理, 该方法会返回有关更新的信息。

详细了解待处理的更新

调用 getPendingSystemUpdate() 后,您可以检查返回的 SystemUpdateInfo 值,以详细了解待处理的更新。通过 以下示例展示了如何找出待处理的更新 可用:

Kotlin

val firstAvailable =
        dpm.getPendingSystemUpdate(adminName)?.receivedTime
firstAvailable?.let {
    Log.i(TAG, "Update first available: ${Date(firstAvailable)}")
}

Java

SystemUpdateInfo updateInfo = dpm.getPendingSystemUpdate(adminName);
if (updateInfo != null) {
  Long firstAvailable = updateInfo.getReceivedTime();
  Log.i(TAG, "Update first available: " + new Date(firstAvailable));
}

系统回调

有可用更新时,Android 系统会通知设备所有者 更新。在 Android 8.0 或更高版本中,系统还会通知个人资料所有者。

DeviceAdminReceiver 子类中,替换 onSystemUpdatePending() 回调。您不需要 来注册或通告您的 DPC,以接收回调。系统可能会 针对单个更新多次调用此方法,因此请检查更新的状态 然后再回复。致电 getPendingSystemUpdate(),详细了解 系统更新以下示例展示如何执行此操作:

Kotlin

/**
 * Called when a new update is available.
 */
override fun onSystemUpdatePending(context: Context?, intent: Intent?,
                                   receivedTime: Long) {

    // System update information is supported in API level 26 or higher.
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        return
    }

    val updateInfo = getManager(context)
            .getPendingSystemUpdate(getWho(context))
            ?: return
    if (updateInfo.securityPatchState ==
            SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE) {
        // Perhaps install because this is a security patch.
        // ...
    }
}

Java

/**
 * Called when a new update is available.
 */
public void onSystemUpdatePending (Context context, Intent intent,
                                   long receivedTime) {

  // System update information is supported in API level 26 or higher.
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    return;
  }
  SystemUpdateInfo updateInfo = getManager(context)
      .getPendingSystemUpdate(getWho(context));
  if (updateInfo == null) {
    return;
  }
  if (updateInfo.getSecurityPatchState() ==
      SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE) {
    // Perhaps install because this is a security patch.
    // ...
  }
}

系统具有多个设备政策控制器 (DPC) 时(例如完全受管的工作资料) 设备,那么设备所有者和资料所有者都会收到回调。

更新政策

设备所有者可以通过设置本地系统来控制何时安装更新 更新政策。系统更新政策可以是以下三种类型之一:

自动
有系统更新后立即安装 (无需用户互动)。设置此政策类型后,系统会立即安装所有待处理的更新 可能会推迟或等待维护期。
带窗
在日常维护期间安装系统更新 窗口(无需用户互动)。创建新的基于时间段的政策时,将每日维护窗口的开始时间和结束时间设置为分钟数。
已延期
将系统更新安装推迟 30 天。30 天后 周期结束时,系统会提示设备用户安装更新。

推迟期

系统会限制每次更新只能推迟 30 天。该周期从以下时间开始算起 系统会首先推迟更新,而设置新的推迟政策 延长时间。

除了推迟之外,Android 可能还会因其他原因(例如无连接、磁盘空间不足或电池电量不足)而无法安装更新。

如果发生其他更新,系统会重置 30 天的推迟计时器 - 让 IT 管理员有机会试用合并的系统 更新。30 天过后,如果没有任何新的更新,系统就会提示 用户安装所有待安装的更新。之后,当出现新的系统更新时 30 天期限将重新开始。

如何设置政策

您可以在 Android 8.0(API 级别 26)或更高版本中设置更新政策。要指定 当设备应安装系统更新时,创建一个 SystemUpdatePolicy,并使用列出的三种类型之一 。如需设置政策,您的设备所有者会调用 DevicePolicyManager 方法 setSystemUpdatePolicy()。以下代码示例展示了如何执行此操作。要查看窗口化政策的示例,请查看 SystemUpdatePolicy 文档。

Kotlin

// Create the system update policy to postpone installation for 30 days.
val policy = SystemUpdatePolicy.createPostponeInstallPolicy()

// Get a DevicePolicyManager instance to set the policy on the device.
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
val adminName = getComponentName(context)

// Set the policy.
dpm.setSystemUpdatePolicy(adminName, policy)

Java

// Create the system update policy to postpone installation for 30 days.
SystemUpdatePolicy policy = SystemUpdatePolicy.createPostponeInstallPolicy();

// Get a DevicePolicyManager instance to set the policy on the device.
DevicePolicyManager dpm = (DevicePolicyManager) context
    .getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminName = getComponentName(context);

// Set the policy.
dpm.setSystemUpdatePolicy(adminName, policy);

政策实例一经创建便无法更改。要更改设备 安装更新,您可以创建和设置新政策。如需从设备中移除政策,请调用 setSystemUpdatePolicy(),并将 null 作为 policy 参数传递。DPC 移除政策后,设备用户会看到任何 可用的系统更新

应用可以调用 getSystemUpdatePolicy() 来获取 设备的当前政策。如果此方法返回 null,则表示 政策。

冻结期

在重要时段(例如节假日或其他繁忙时段)冻结操作系统版本 次,设备所有者最长可以暂停系统更新 90 天。当 设备处于冻结期内,其行为如下:

  • 设备不会收到任何有关待处理系统更新的通知。
  • 未安装操作系统的系统更新。
  • 设备用户无法在“设置”中手动检查系统更新。

在出现任何定义的冻结之后,系统会强制执行 60 天的缓冲期 以防止无限期冻结设备。记住,系统死机 更新可能会导致设备无法接收重要更新。

图 1.为设备设置两个冻结期
显示一年中两次冻结期的日历,具有 60 天缓冲期。

您可以为更新政策设置冻结期。您无法设置冻结时段, 设置政策当设备处于您设置的冻结期之外时, 应用正常的政策行为(自动、窗口化或推迟)。

如何设置冻结期

您可以在 Android 9(API 级别 28)或更高版本中设置冻结期。设备 所有者在设置系统更新政策之前设置冻结期 。步骤如下:

  1. 创建新的(或获取当前的)系统更新政策。
  2. 调用 setFreezePeriods() 来设置政策的冻结期。
  3. 通过调用为设备设置政策和冻结时段 setSystemUpdatePolicy()

由于冻结期每年都会重复,因此冻结期的开始日期和结束日期 都用月值和日值表示开始日期必须于 至少 60 天。以下示例 展示了如何为现有系统更新政策设置两个冻结期:

Kotlin

// Get the existing policy from the DevicePolicyController instance.
val policy = dpm.systemUpdatePolicy ?: return

try {
    // Set the two annual freeze periods on the policy for our retail
    // point-of-sale devices.
    val summerSale = FreezePeriod(
            MonthDay.of(6, 1),
            MonthDay.of(7, 31)) // Jun 1 - Jul 31 inclusive
    val winterSale = FreezePeriod(
            MonthDay.of(11, 20),
            MonthDay.of(1, 12)) // Nov 20 - Jan 12 inclusive
    policy.freezePeriods = Arrays.asList(summerSale, winterSale)

    // Set the policy again to activate the freeze periods.
    dpm.setSystemUpdatePolicy(adminName, policy)

} catch (e: SystemUpdatePolicy.ValidationFailedException) {
    // There must be previous periods recorded on the device because
    // summerSale and winterSale don’t overlap and are separated by more
    // than 60 days. Report the overlap ...
}

Java

// Get the existing policy from the DevicePolicyController instance.
SystemUpdatePolicy policy = dpm.getSystemUpdatePolicy();

try {
  // Set the two annual freeze periods on the policy for our
  // retail point-of-sale devices.
  FreezePeriod summerSale = new FreezePeriod(
      MonthDay.of(6, 1),
      MonthDay.of(7, 31)); // Jun 1 - Jul 31 inclusive
  FreezePeriod winterSale = new FreezePeriod(
      MonthDay.of(11, 20),
      MonthDay.of(1, 12)); // Nov 20 - Jan 12 inclusive
  policy.setFreezePeriods(Arrays.asList(summerSale, winterSale));

  // Don’t forget to set the policy again to activate the freeze periods.
  dpm.setSystemUpdatePolicy(adminName, policy);

} catch (SystemUpdatePolicy.ValidationFailedException e) {
  // There must be previous periods recorded on the device because summerSale
  // and winterSale don’t overlap and are separated by more than 60 days.
  // Report the overlap ...
}

开始日期和结束日期都包含在内。如果开始日期晚于 比结束日期(例如,上例中的 winterSale)多,则冻结 延长至下一年。

设置冻结时 系统更新政策的期限内,Android 会测试以下要求:

  • 冻结期不会超过 90 天。
  • 冻结期之间的间隔至少为 60 天。
  • 冻结期不会重叠。
  • 没有重复的冻结期。

为设备设置系统更新政策时,Android 会重复这些测试 包括设备当前或过去的任何冻结期。

当发生以下情况时,Android 会抛出 SystemUpdatePolicy.ValidationFailedException: 任何一项测试失败

要获取之前在系统更新政策对象上设置的冻结期列表, 所有已安装的应用都可以调用 SystemUpdatePolicy.getFreezePeriods()。以下 示例会调用此方法来记录设备的冻结期:

Kotlin

// Log any freeze periods that might be set on a system update policy.
dpm.systemUpdatePolicy?.freezePeriods?.forEach {
    Log.i(TAG, "Freeze period: $it")
}

Java

// Log any freeze periods that might be set on a system update policy.
SystemUpdatePolicy currentPolicy = dpm.getSystemUpdatePolicy();
if (currentPolicy != null) { // A policy might not be set.
  for (FreezePeriod freezePeriod : currentPolicy.getFreezePeriods()) {
    Log.i(TAG, "Freeze period: " + freezePeriod.toString());
  }
}

闰年

Android 使用 ISO 8601 日历(也称为公历)来 计算冻结期,并且忽略闰年。也就是说 被识别为有效日期,会被视为 2 月 28 日。 因此在计算冻结时长时,系统不会将 2 月 29 日的数据统计在内 。

开发和测试

在开发和测试 DPC 的系统更新功能时,您可能 就需要创建多个冻结期因为 Android 会以 60 天为时间间隔进行检查 ,那么您可能无法设置新的冻结期 而不会先清除过去经期的记录。清除设备冻结状态 记录期间,请在 Android 调试桥中运行以下命令 (adb) shell:

adb shell dpm clear-freeze-period-record

您可以通过检查用户是否 系统更新界面已停用。

Google Play 系统更新 (Mainline)

Google Play 系统更新(也称为 Mainline 更新)是指 自动下载,但需要重新启动设备才能安装。这些 更新不会触发自动重新启动,而是会安装在 下次用户、管理员或政策启动的重新启动时。由系统更新政策触发的重启会安装关联的 Google/OEM 系统更新以及之前下载的所有 Google Play 系统更新。

Google Play 系统更新也可以手动安装,方法是转到 设置 >关于 >Android 版本 >Google Play 系统更新

回滚更新

在某些情况下,Google Play 系统更新回滚 (GPSUR) 工具可以 用于恢复设备状态(由于 Google Play 系统更新出现问题) 安装。只有高级用户或在支持人员指示的情况下才能使用此工具,因为它可能会导致数据丢失。使用 GPSUR 的 工具:

  1. 如果您在计算机上运行 Android 调试桥 (adb),请先停止 adb 服务,然后再继续操作,以免该服务干扰回滚过程。如需停止 adb,请运行 adb kill-server
  2. 打开 GPSUR 工具
  3. 点击允许 ADB 访问,以允许该工具通过 adb 与您的测试设备通信。
  4. 点击添加新设备
  5. 从列表中选择您的设备,然后点击连接。此列表可能未 包含完整的设备名称。
  6. 在设备屏幕上,选择一律允许使用这台计算机进行调试,然后点击 确定接受 USB 调试连接。
  7. 在浏览器中选择已连接的设备。
  8. 如果您的设备上有可用的回滚,页面上的按钮文本应从无可用的回滚切换为回滚近期更新。点击回滚最近更新
  9. 阅读确认回滚模态窗口中的警告,然后点击确认
  10. 等待回滚完成。完成后,系统会显示回滚成功 模态窗口,设备将重新启动。现在可以安全地拔下 设备。

其他资源

要详细了解系统更新,请参阅 Android 开源项目的 OTA 更新文档。