이 개발자 가이드에서는 기기 정책 컨트롤러 (DPC)가 기기 사용자를 대신하여 Android 시스템 업데이트를 관리하는 방법을 설명합니다.
소개
Android 기기는 OTA (over-the-air) 업데이트를 수신하여 시스템 및 애플리케이션 소프트웨어에 설치할 수 있습니다. Android는 시스템 업데이트를 사용할 수 있으며 기기 사용자가 업데이트를 즉시 또는 나중에 설치할 수 있다고 기기 사용자에게 알립니다.
IT 관리자는 DPC를 사용하여 기기 사용자를 위한 시스템 업데이트를 관리할 수 있습니다. DPC는 완전 관리형 기기 (기기 소유자라고 함)를 소유하거나 직장 프로필(프로필 소유자라고 함)을 소유할 수 있습니다. 표 1은 기기 소유자가 시스템 업데이트를 관리하는 반면 프로필 소유자는 시스템 업데이트에 관한 정보만 보고할 수 있는 방법을 보여줍니다.
표 1: DPC에서 사용할 수 있는 작업은 소유자 모드에 따라 다름
작업 | 기기 소유자 | 프로필 소유자 |
---|---|---|
대기 중인 시스템 업데이트 확인하기 | ||
새로운 시스템 업데이트가 있을 때 콜백 받기 | ||
로컬 업데이트 정책을 설정하여 Android에서 시스템 업데이트를 설치하는 시기 제어 | ||
중요한 기간 동안 OS 버전 고정 |
대기 중인 업데이트 확인
대기 중인 업데이트는 아직 설치되지 않은 기기의 시스템 업데이트입니다. DPC를 사용하면 IT 관리자가 시스템 업데이트가 대기 중인 기기를 확인하고 기기 사용자에게 중요 업데이트를 즉시 설치하도록 요청할 수 있습니다.
Android 8.0 (API 수준 26) 이상에서 실행되는 기기 소유자 및 프로필 소유자는 기기에 대기 중인 시스템 업데이트가 있는지 확인할 수 있습니다. 기기가 최신 상태라면 null
를 반환하는 DevicePolicyManager.getPendingSystemUpdate()
를 호출합니다. 시스템 업데이트가 대기 중인 경우 이 메서드는 업데이트에 관한 정보를 반환합니다.
대기 중인 업데이트에 관해 자세히 알아보기
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일이 지나면 시스템은 기기 사용자에게 업데이트를 설치하라는 메시지를 표시합니다.
연기 기간
시스템에서는 각 업데이트를 1회 연기할 수 있도록 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);
정책 인스턴스를 만든 후에는 변경할 수 없습니다. 기기가 업데이트를 설치하는 시점을 변경하려면 새 정책을 만들고 설정하면 됩니다. 기기에서 정책을 삭제하려면 null
를 policy
인수로 전달하는 setSystemUpdatePolicy()
를 호출합니다.
DPC에서 정책을 삭제하면 사용 가능한 시스템 업데이트에 관한 알림이 기기 사용자에게 표시됩니다.
앱은 getSystemUpdatePolicy()
를 호출하여 기기의 현재 정책을 가져올 수 있습니다. 이 메서드가 null
를 반환하면 정책이 현재 설정되지 않은 것입니다.
정지 기간
중요한 기간(예: 휴일 또는 기타 사용량이 많은 시간)에 OS 버전을 고정하기 위해 기기 소유자는 최대 90일 동안 시스템 업데이트를 정지할 수 있습니다. 기기가 정지 기간 내에 있으면 다음과 같이 작동합니다.
- 기기가 대기 중인 시스템 업데이트에 관한 알림을 수신하지 않습니다.
- OS의 시스템 업데이트가 설치되지 않았습니다.
- 기기 사용자는 설정에서 시스템 업데이트를 수동으로 확인할 수 없습니다.
시스템은 정의된 정지 기간 후 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월 29일은 유효한 날짜로 인식되지 않으며 2월 28일인 것처럼 처리됩니다. 따라서 정지 기간을 계산할 때 2월 29일은 포함되지 않습니다.
개발 및 테스트
DPC의 시스템 업데이트 기능을 개발하고 테스트하는 동안 정지 기간을 많이 만들어야 할 수 있습니다. Android에서는 지난 정지 기간 사이의 60일 간격을 확인하기 때문에 이전 기간의 기록을 먼저 지우지 않으면 새 정지 기간을 설정하지 못할 수도 있습니다. 기기의 정지 기간 기록을 삭제하려면 Android 디버그 브리지(adb) 셸에서 다음 명령어를 실행합니다.
adb shell dpm clear-freeze-period-record
시스템 업데이트를 위한 사용자 인터페이스가 사용 중지되어 있는지 확인하여 기기가 정지 기간인지 확인할 수 있습니다.
추가 리소스
시스템 업데이트에 관한 자세한 내용은 Android 오픈소스 프로젝트의 OTA 업데이트 문서를 참고하세요.