管理系統更新

本開發人員指南說明裝置政策控制器 (DPC) 如何代表裝置使用者管理 Android 系統更新。

簡介

Android 裝置可以接收並安裝系統無線更新 (OTA) 和應用程式軟體Android 會通知裝置使用者進行系統更新 可以使用,且裝置使用者可以立即安裝更新,也可以稍後安裝。

IT 管理員可以透過 DPC 管理裝置使用者的系統更新。DPC 可以擁有全代管裝置 (稱為裝置擁有者),也可以擁有工作資料夾 (稱為設定檔擁有者)。表 1 說明裝置擁有者如何管理系統 更新,但個人資料擁有者只能回報系統更新相關資訊。

表 1:DPC 可使用的工作取決於擁有者模式

工作 裝置擁有者 設定檔擁有者
檢查是否有待處理的系統更新
在有新系統更新時接收回呼
設定本機更新政策,控制 Android 安裝系統更新的時間
凍結重要期間的 OS 版本

檢查是否有待處理的更新

待更新是指尚未安裝的裝置系統更新。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,表示目前未設定政策。

凍結期間

在重要期間 (例如假日或其他忙碌期間) 期間凍結 OS 版本 時間,裝置擁有者可暫停系統更新,最長可達 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 月 29 日 無法識別為有效日期,並視為 2 月 28 日。 因此,2 月 29 日的凍結期間不會列入計算 。

開發和測試

開發及測試 DPC 的系統更新功能時,您可能需要建立許多凍結期間。由於 Android 會檢查 因此你可能無法設定新的凍結期間 而不需要先清除過去的經期記錄。如要清除裝置的凍結期間記錄,請在 Android Debug Bridge (adb) 殼層中執行下列指令:

adb shell dpm clear-freeze-period-record

如要確認裝置處於凍結期間,請檢查系統更新的使用者介面是否已停用。

Google Play 系統更新 (Mainline)

Google Play 系統更新 (也稱為 Mainline 更新) 是 自動下載,但需要重新啟動裝置才能安裝。這類更新不會讓裝置自動重新啟動,而且會等待使用者、管理員或政策下次重新啟動裝置時再安裝。由系統觸發的重新啟動 更新政策會安裝相關聯的 Google/原始設備製造商 (OEM) 系統更新 下載先前下載的 Google Play 系統更新

您也可以前往 設定 >關於 >Android 版本 >Google Play 系統更新

復原更新

在某些情況下,如果 Google Play 系統更新安裝作業發生問題,您可以使用 Google Play 系統更新回溯 (GPSUR) 工具來復原裝置狀態。這項工具適合進階使用者或指示 所以可能會遺失資料以下是 GPSUR 工具的使用方式:

  1. 如果您已在電腦上執行 Android Debug Bridge (ADB),請停止 再繼續作業,以免干擾 復原程序。如要停止 ADB,請執行 adb kill-server
  2. 開啟 GPSUR 工具
  3. 按一下「允許 ADB 存取」,允許工具透過 ADB 與測試裝置通訊。
  4. 按一下「新增裝置」
  5. 從清單中選取裝置,然後按一下「連結」。這份清單不一定 包含完整裝置名稱。
  6. 在裝置的螢幕上選取「一律允許透過這台電腦進行」,然後按一下 確定接受 USB 偵錯連線。
  7. 在瀏覽器中選取已連結的裝置。
  8. 頁面上的按鈕文字應從「No Rollbacks available」切換成「No Rollbacks available」 如果裝置有復原版本,可以復原近期更新。 按一下「還原最近的更新」
  9. 閱讀「確認回溯」對話方塊中的警告,然後按一下「確認」
  10. 等待還原作業完成。完成後,畫面上會顯示「Rollback Successful」訊息,裝置也會重新啟動。現在可以放心拔除裝置了。

其他資源

如要進一步瞭解系統更新,請參閱 Android 開放原始碼專案的 OTA 更新說明文件。