本开发者指南介绍了设备政策控制器 (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 天缓冲期,以防止无限期冻结设备。请注意,冻结系统更新可能会阻止设备接收关键更新。
您可以为更新政策设置冻结期。您无法设置冻结时段, 设置政策当设备不在您设置的任何���结期内时,系统会应用正常的政策行为(自动、窗口化或推迟)。
如何设置冻结期
您可以在 Android 9(API 级别 28)或更高版本中设置冻结期。设备 所有者在设置系统更新政策之前设置冻结期 。步骤如下:
- 创建新的(或获取当前的)系统更新政策。
- 通过调用
setFreezePeriods()。 - 通过调用为设备设置政策和冻结时段
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 工具的使用方法如下:
- 如果您在计算机上运行 Android 调试桥 (adb),请先停止 adb 服务,然后再继续操作,以免该服务干扰回滚过程。如需停止 adb,请运行
adb kill-server。 - 打开 GPSUR 工具。
- 点击允许 ADB 访问,以允许该工具通过 adb 与您的测试设备通信。
- 点击添加新设备。
- 从列表中选择您的设备,然后点击连接。此列表不一定包含完整的设备名称。
- 在设备屏幕上,选择一律允许使用这台计算机进行调试,然后点击 确定接受 USB 调试连接。
- 在浏览器中选择已连接的设备。
- 如果您的设备上有可用的回滚,页面上的按钮文本应从无可用的回滚切换为回滚近期更新。点击回滚近期更新。
- 阅读确认回滚模态窗口中的警告,然后点击确认。
- 等待回滚完成。完成后,系统会显示回滚成功 模态窗口,设备将重新启动。现在可以安全地拔下 设备。
其他资源
要详细了解系统更新,请参阅 Android 开源项目的 OTA 更新文档。