管理系統更新

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

簡介

Android 裝置可以接收及安裝系統和應用程式軟體的無線更新 (OTA)。Android 會通知裝置使用者有可用的系統更新,裝置使用者可以立即安裝更新,或是稍後安裝。

IT 管理員可透過 DPC,管理裝置使用者的系統更新。裝置政策控制器可以擁有全代管裝置 (稱為裝置擁有者),或擁有工作資料夾 (稱為「設定檔擁有者」)。表 1 說明裝置擁有者如何管理系統更新,而設定檔擁有者則只能回報系統更新的相關資訊。

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

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

檢查是否有待更新

待安裝的更新指的是裝置尚未安裝的系統更新。 IT 管理員可協助 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(),並以 policy 引數形式傳遞 null。DPC 移除政策後,裝置使用者就會看到任何可用系統更新的通知。

應用程式可以呼叫 getSystemUpdatePolicy() 來取得裝置目前的政策。如果這個方法傳回 null,表示目前未設定政策。

凍結期間

如要在重要時段 (例如假日或其他忙碌時段) 凍結 OS 版本,裝置擁有者最多可以暫停系統更新 90 天。如果裝置處於凍結期間,運作情形如下:

  • 裝置不會收到任何有關待處理系統更新的通知。
  • 未安裝 OS 的系統更新。
  • 裝置使用者無法在「設定」中手動檢查系統更新。

在任何定義的凍結期間,系統會強制執行 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());
  }
}

Leap 年

Android 使用 ISO 8601 日曆 (又稱為公曆) 計算凍結期間,忽略葉年。這表示系統無法將 2 月 29 日視為有效日期,系統會將該日期視為 2 月 28 日。因此,2 月 29 日之後,計算凍結期間的持續時間就不會計入。

開發和測試

在開發及測試 DPC 的系統更新功能時,您可能需要建立多個凍結期間。由於 Android 會檢查過去的凍結期間之間 60 天的間隔,因此您可能必須先清除過去的記錄,才能設定新的凍結期間。如要清除裝置的凍結期間記錄,請在 Android Debug Bridge (ADB) 殼層中執行下列指令:

adb shell dpm clear-freeze-period-record

您可以透過檢查系統更新的使用者介面,確認裝置是否處於凍結期間。

其他資源

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