คู่มือนี้อธิบายวิธีใช้ Android Management API (AMAPI) SDK ในเครื่องมือควบคุมนโยบายด้านอุปกรณ์ (DPC) ที่กำหนดเองเพื่อกำหนดค่าการควบคุมการอัปเดตแบบรวม (UUC) ในอุปกรณ์ของบริษัท
เมื่อใช้ AMAPI SDK แล้ว DPC ที่กำหนดเองจะส่งนโยบาย UUC ไปยังแอป Android Device Policy (ADP) ในอุปกรณ์โดยตรง ADP จะประเมินกฎนโยบายเทียบกับสถานะปัจจุบันของอุปกรณ์ และแนะนำ Google Play และไคลเอ็นต์ OTA ของ OEM เกี่ยวกับวิธีจัดการการอัปเดตที่รอดำเนินการ
ก่อนเริ่มต้น โปรดอ่านการควบคุมการอัปเดตแบบรวมเพื่อดูวิธีการทำงานของกฎ เป้าหมาย เพรดิเคต และผลลัพธ์ รวมถึงข้อจำกัดที่ใช้กับการผสานรวม UUC ทั้งหมด
ข้อกำหนดเบื้องต้น
ก่อนผสานรวม UUC เข้ากับ DPC ที่กำหนดเอง ให้ตรวจสอบข้อกำหนดต่อไปนี้
- อุปกรณ์เป็นของบริษัท ซึ่งกำหนดค่าเป็นอุปกรณ์ที่มีการจัดการครบวงจรหรือมีโปรไฟล์งานในอุปกรณ์ของบริษัท
- DPC ที่กำหนดเองของคุณผสานรวมกับ AMAPI SDK
- อุปกรณ์ได้รับการลงทะเบียนโดยใช้ Google Play EMM API
- อุปกรณ์เป็นไปตามข้อกำหนดเวอร์ชันขั้นต่ำสำหรับโหมดการจัดการและเป้าหมายการอัปเดตแต่ละรายการที่คุณต้องการควบคุม ดังนี้
- อุปกรณ์ที่มีการจัดการครบวงจร (เจ้าของอุปกรณ์): Android 13 (ระดับ API 33) ขึ้นไป
- อุปกรณ์ของบริษัทที่มีโปรไฟล์งาน (COPE): Android 15 (API ระดับ 35) ขึ้นไป
ผสานรวมกับ AMAPI SDK ใน DPC ที่กำหนดเอง
หากต้องการกำหนดค่านโยบาย UUC ในอุปกรณ์ DPC ที่กำหนดเองต้องผสานรวมกับ AMAPI SDK ดูวิธีการเพิ่มไลบรารีและกำหนดค่าไฟล์ Manifest ของแอปได้ที่คู่มือการผสานรวม AMAPI SDK
ขั้นตอนในการกำหนดค่าการควบคุมการอัปเดตแบบรวม
หากต้องการกำหนดค่านโยบาย UUC จาก DPC ที่กำหนดเอง ให้ตรวจสอบว่าสภาพแวดล้อมของไคลเอ็นต์ในอุปกรณ์พร้อมใช้งานและเป็นเวอร์ชันล่าสุดก่อนส่งคำขอนโยบายไปยัง ADP โดยทำดังนี้
- ยืนยันสภาพแวดล้อมของไคลเอ็นต์
- เตรียมสภาพแวดล้อมของไคลเอ็นต์
- ตั้งค่า ดึงข้อมูล และล้างนโยบายการอัปเดต
ยืนยันสภาพแวดล้อมของไคลเอ็นต์
ตัวอย่างต่อไปนี้แสดงวิธีเรียกใช้ getEnvironment (ใน Kotlin) หรือ getEnvironmentAsync (ใน Java) ด้วย Role.RoleType.DEVICE_POLICY_CONTROLLER เพื่อตรวจสอบสถานะของแอป ADP หากสภาพแวดล้อมเป็น READY และ UP_TO_DATE DPC ที่กำหนดเองจะกำหนดค่านโยบาย UUC โดยใช้ PolicyClient ได้ หรือเรียกใช้ prepareEnvironment เพื่อติดตั้งหรืออัปเดตแอป ADP (ดูหัวข้อเตรียมสภาพแวดล้อมของไคลเอ็นต์)
Kotlin
import android.content.Context import android.util.Log import com.google.android.managementapi.common.model.Role import com.google.android.managementapi.environment.EnvironmentClientFactory import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.INSTALLED import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.NOT_INSTALLED import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE import com.google.android.managementapi.environment.model.GetEnvironmentRequest private suspend fun checkEnvironmentForUuc(context: Context): Boolean { try { val roles = listOf( Role.builder() .setRoleType(Role.RoleType.DEVICE_POLICY_CONTROLLER) .build() ) val request = GetEnvironmentRequest.builder().setRoles(roles).build() val environmentClient = EnvironmentClientFactory.create(context) val environmentResponse = environmentClient.getEnvironment(request) if (environmentResponse.hasAndroidDevicePolicyEnvironment()) { val adpEnvironment = environmentResponse.androidDevicePolicyEnvironment when (adpEnvironment.state) { READY -> { return if (adpEnvironment.version == UP_TO_DATE) { // AMAPI environment state and version are ready. true } else { prepareEnvironment(context, environmentClient) } } INSTALLED -> { // Call prepareEnvironment to silently update ADP. return prepareEnvironment(context, environmentClient) } NOT_INSTALLED -> { // Call prepareEnvironment to install ADP. return prepareEnvironment(context, environmentClient) } else -> {} } } } catch (e: Exception) { Log.e(TAG, "Exception checking environment", e) } return false }
Java
import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.INSTALLED; import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.NOT_INSTALLED; import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY; import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE; import android.content.Context; import android.util.Log; import com.google.android.managementapi.common.model.Role; import com.google.android.managementapi.environment.EnvironmentClient; import com.google.android.managementapi.environment.EnvironmentClientFactory; import com.google.android.managementapi.environment.model.Environment; import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment; import com.google.android.managementapi.environment.model.GetEnvironmentRequest; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; private void checkEnvironmentForUuc(Context context) { try { ImmutableListroles = new ImmutableList.Builder () .add(Role.builder() .setRoleType(Role.RoleType.DEVICE_POLICY_CONTROLLER) .build()) .build(); EnvironmentClient environmentClient = EnvironmentClientFactory.create(context); GetEnvironmentRequest getRequest = GetEnvironmentRequest.builder() .setRoles(roles) .build(); ListenableFuture getEnvironmentFuture = environmentClient.getEnvironmentAsync(getRequest); Futures.addCallback(getEnvironmentFuture, new FutureCallback () { @Override public void onSuccess(Environment environment) { if (!environment.hasAndroidDevicePolicyEnvironment()) { return; } AndroidDevicePolicyEnvironment adpEnvironment = environment.getAndroidDevicePolicyEnvironment(); AndroidDevicePolicyEnvironment.State state = adpEnvironment.getState(); AndroidDevicePolicyEnvironment.Version version = adpEnvironment.getVersion(); if (state == READY && version == UP_TO_DATE) { // AMAPI environment state and version are ready. return; } else if (state == INSTALLED || state == NOT_INSTALLED) { // Call prepareEnvironment to silently install or update ADP. prepareEnvironment(context, environmentClient); } } @Override public void onFailure(Throwable t) { Log.e(TAG, "Failed to verify environment", t); } }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.e(TAG, "Exception verifying environment", e); } }
เตรียมสภาพแวดล้อมของไคลเอ็นต์
หากสภาพแวดล้อมในอุปกรณ์ไม่พร้อมใช้งานหรือไม่อัปเดต ให้เรียกใช้ prepareEnvironment ก่อนใช้ PolicyClient
เมื่อเรียกจาก DPC ที่กำหนดเองด้วย Role.RoleType.DEVICE_POLICY_CONTROLLER และชื่อคอมโพเนนต์ DeviceAdminReceiver ของ DPC ที่ส่งไปยัง setAdmin(), prepareEnvironment จะติดตั้งแอป ADP แบบเงียบ (หากยังไม่ได้ติดตั้ง) และอัปเดตแอป ADP และ Google Play Store โดยไม่ต้องมีการโต้ตอบจากผู้ใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเตรียมสภาพแวดล้อมในขั้นตอน DPC ที่กำหนดเองได้ที่หัวข้อการเตรียมสภาพแวดล้อมและการลงทะเบียนผู้ใช้
Kotlin
import android.content.ComponentName import android.content.Context import android.util.Log import com.google.android.managementapi.common.model.Role import com.google.android.managementapi.environment.EnvironmentClient import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE import com.google.android.managementapi.environment.model.PrepareEnvironmentRequest private suspend fun prepareEnvironment( context: Context, environmentClient: EnvironmentClient ): Boolean { try { val roles = listOf( Role.builder() .setRoleType(Role.RoleType.DEVICE_POLICY_CONTROLLER) .build() ) val request = PrepareEnvironmentRequest.builder() .setRoles(roles) .setAdmin( ComponentName( context, DeviceAdminReceiver::class.java ) ) .build() val response = environmentClient.prepareEnvironment(request, null) val environment = response.environment val adpEnvironment = environment.androidDevicePolicyEnvironment val state = adpEnvironment.state val version = adpEnvironment.version return (state == READY && version == UP_TO_DATE) } catch (e: Exception) { Log.e(TAG, "Failed to prepare environment", e) } return false }
Java
import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY; import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE; import android.content.ComponentName; import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; import com.google.android.managementapi.common.model.Role; import com.google.android.managementapi.environment.EnvironmentClient; import com.google.android.managementapi.environment.model.Environment; import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment; import com.google.android.managementapi.environment.model.PrepareEnvironmentRequest; import com.google.android.managementapi.environment.model.PrepareEnvironmentResponse; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; private void prepareEnvironment(Context context, EnvironmentClient environmentClient) { try { ImmutableListroles = new ImmutableList.Builder () .add(Role.builder() .setRoleType(Role.RoleType.DEVICE_POLICY_CONTROLLER) .build()) .build(); ComponentName adminComponent = new ComponentName( context, DeviceAdminReceiver.class ); PrepareEnvironmentRequest request = PrepareEnvironmentRequest.builder() .setRoles(roles) .setAdmin(adminComponent) .build(); ListenableFuture environmentFuture = environmentClient.prepareEnvironmentAsync(request, null); Futures.addCallback(environmentFuture, new FutureCallback () { @Override public void onSuccess(PrepareEnvironmentResponse response) { Environment environment = response.getEnvironment(); AndroidDevicePolicyEnvironment adpEnvironment = environment.getAndroidDevicePolicyEnvironment(); AndroidDevicePolicyEnvironment.State state = adpEnvironment.getState(); AndroidDevicePolicyEnvironment.Version version = adpEnvironment.getVersion(); if (state == READY && version == UP_TO_DATE) { // Environment is prepared; configure UUC policy using PolicyClient. } else { Log.w( TAG, "AMAPI environment was not ready: " + state + " - " + version ); } } @Override public void onFailure(@NonNull Throwable t) { Log.e(TAG, "Failed to prepare environment", t); } }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.e(TAG, "Exception preparing environment", e); } }
ตั้งค่า ดึงข้อมูล และล้างนโยบายการอัปเดต
หลังจากสภาพแวดล้อมพร้อมแล้ว ให้ใช้ PolicyClient (สร้างด้วย PolicyClientFactory.create(context)) เพื่อใช้ Policy ที่มีกฎ UnifiedUpdatePolicy ตรวจสอบนโยบายที่ใช้งานอยู่ หรือล้างนโยบาย UUC ออกจากอุปกรณ์
คำแนะนำการใช้งาน PolicyClient
การสร้างอินสแตนซ์ PolicyClient จะสร้างช่องทางการสื่อสารกับแอป ADP เพื่อเพิ่มประสิทธิภาพ เราขอแนะนำให้สร้างอินสแตนซ์ PolicyClient รายการเดียวโดยใช้ PolicyClientFactory.create() และแคชไว้เพื่อนำมาใช้ซ้ำในแอปพลิเคชัน หลีกเลี่ยงการสร้างอินสแตนซ์ PolicyClient ใหม่ขณะที่อินสแตนซ์อื่นทำงานอยู่ เนื่องจากอาจทำให้ช่องทางการสื่อสารที่มีอยู่ปิดลง ซึ่งจะทำให้เกิดค่าใช้จ่ายเพิ่มเติมและอาจทำให้ทรัพยากรรั่วไหลได้
กำหนดนโยบายการอัปเดต
หากต้องการใช้กฎ UUC ให้สร้าง Policy.UnifiedUpdatePolicy ที่มีรายการออบเจ็กต์ Rule แนบกับ Policy ภายใน UpdatePolicyRequest แล้วเรียกใช้ updatePolicy (ใน Kotlin) หรือ updatePolicyFuture (ใน Java) ดังนี้
Kotlin
import android.util.Log import com.google.android.managementapi.policy.PolicyClient import com.google.android.managementapi.policy.model.Policy import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule import com.google.android.managementapi.policy.model.UpdatePolicyRequest suspend fun setUucPolicy( policyClient: PolicyClient, rules: Iterable): Boolean { // Build the UnifiedUpdatePolicy and attach it to the overall Policy. val unifiedUpdatePolicy = Policy.UnifiedUpdatePolicy.builder() .setRules(rules) .build() val policy = Policy.builder() .setUnifiedUpdatePolicy(unifiedUpdatePolicy) .build() // Create the UpdatePolicyRequest. val updateRequest = UpdatePolicyRequest.builder() .setPolicy(policy) .build() // Apply the policy using PolicyClient within a CoroutineScope. return try { val updatedPolicy = policyClient.updatePolicy(updateRequest) Log.d(TAG, "Policy updated successfully: $updatedPolicy") true } catch (e: Exception) { Log.e(TAG, "Error updating policy: ${e.message}", e) false } }
Java
import android.util.Log; import com.google.android.managementapi.policy.PolicyClient; import com.google.android.managementapi.policy.model.Policy; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule; import com.google.android.managementapi.policy.model.UpdatePolicyRequest; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import java.util.stream.Collectors; import java.util.stream.StreamSupport; ListenableFuturesetUucPolicy( PolicyClient policyClient, Iterable rules ) { // Build the UnifiedUpdatePolicy and attach it to the overall Policy. UnifiedUpdatePolicy unifiedUpdatePolicy = UnifiedUpdatePolicy.builder() .setRules( StreamSupport.stream(rules.spliterator(), false) .collect(Collectors.toList()) ) .build(); Policy policy = Policy.builder() .setUnifiedUpdatePolicy(unifiedUpdatePolicy) .build(); // Create the UpdatePolicyRequest. UpdatePolicyRequest updateRequest = UpdatePolicyRequest.builder() .setPolicy(policy) .build(); // Apply the policy using PolicyClient. try { ListenableFuture updateFuture = policyClient.updatePolicyFuture(updateRequest); return Futures.transform(updateFuture, updatedPolicy -> { Log.d(TAG, "Policy updated successfully: " + updatedPolicy); return true; }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.e(TAG, "Error updating policy: " + e.getMessage(), e); return Futures.immediateFuture(false); } }
ดึงข้อมูลนโยบายการอัปเดตที่ใช้งานอยู่
หากต้องการตรวจสอบนโยบาย UUC ที่ใช้งานอยู่ในอุปกรณ์ ให้สร้าง GetPolicyRequest และเรียกใช้ getPolicy (ใน Kotlin) หรือ getPolicyFuture (ใน Java) ใช้ hasUnifiedUpdatePolicy() กับ Policy ที่แสดงผลเพื่อตรวจสอบว่ามีการกำหนดค่านโยบาย UUC หรือไม่
Kotlin
import android.util.Log import com.google.android.managementapi.policy.PolicyClient import com.google.android.managementapi.policy.model.GetPolicyRequest import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule suspend fun getActiveUucPolicy(policyClient: PolicyClient) { try { val getPolicyRequest = GetPolicyRequest.builder().build() val activePolicy = policyClient.getPolicy(getPolicyRequest) Log.i(TAG, "Policy version: ${activePolicy.version}") if (!activePolicy.hasUnifiedUpdatePolicy()) { Log.i(TAG, "No Unified Update Policy set.") return } val activeUucPolicy = activePolicy.unifiedUpdatePolicy val rules: List= activeUucPolicy.rules.toList() rules.forEachIndexed { index, rule -> val outcome = if (rule.hasOutcome()) rule.outcome.toString() else "[no outcome]" val predicate = if (rule.hasPredicate()) rule.predicate.toString() else "[no predicate]" Log.i(TAG, "Rule [$index] targets: ${rule.targets}") Log.i(TAG, "Rule [$index] outcome: $outcome") Log.i(TAG, "Rule [$index] predicate: $predicate") } } catch (e: Exception) { Log.e(TAG, "Error retrieving policy: ${e.message}", e) } }
Java
import android.util.Log; import com.google.android.managementapi.policy.PolicyClient; import com.google.android.managementapi.policy.model.GetPolicyRequest; import com.google.android.managementapi.policy.model.Policy; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import java.util.List; import java.util.stream.Collectors; import java.util.stream.StreamSupport; void getActiveUucPolicy(PolicyClient policyClient) { try { GetPolicyRequest getPolicyRequest = GetPolicyRequest.builder().build(); ListenableFuturegetActivePolicy = policyClient.getPolicyFuture(getPolicyRequest); Futures.addCallback(getActivePolicy, new FutureCallback () { @Override public void onSuccess(Policy result) { if (!result.hasUnifiedUpdatePolicy()) { Log.i(TAG, "No Unified Update Policy set."); return; } UnifiedUpdatePolicy activeUucPolicy = result.getUnifiedUpdatePolicy(); List uucRules = StreamSupport.stream( activeUucPolicy.getRules().spliterator(), false) .collect(Collectors.toList()); for (int i = 0; i < uucRules.size(); i++) { Rule rule = uucRules.get(i); String outcome = rule.hasOutcome() ? rule.getOutcome().toString() : "[no outcome]"; String predicate = rule.hasPredicate() ? rule.getPredicate().toString() : "[no predicate]"; Log.i(TAG, "Rule [" + i + "] targets: " + rule.getTargets()); Log.i(TAG, "Rule [" + i + "] outcome: " + outcome); Log.i(TAG, "Rule [" + i + "] predicate: " + predicate); } } @Override public void onFailure(Throwable t) { Log.e(TAG, "Error retrieving policy", t); } }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.e(TAG, "Exception retrieving policy", e); } }
ล้างนโยบายการอัปเดต
หากต้องการนำ UnifiedUpdatePolicy ออกจากอุปกรณ์โดยไม่ล้างช่องอื่นๆ ใน Policy ให้ดึงข้อมูล Policy ปัจจุบันโดยใช้ getPolicy, เรียกใช้ currentPolicy.toBuilder().clearUnifiedUpdatePolicy().build() และใช้ Policy ที่อัปเดตแล้ว
Kotlin
import android.util.Log import com.google.android.managementapi.policy.PolicyClient import com.google.android.managementapi.policy.model.GetPolicyRequest import com.google.android.managementapi.policy.model.UpdatePolicyRequest suspend fun clearUucPolicy(policyClient: PolicyClient): Boolean { try { // 1. Retrieve the current policy. val currentPolicy = policyClient.getPolicy( GetPolicyRequest.builder().build() ) if (!currentPolicy.hasUnifiedUpdatePolicy()) { Log.i(TAG, "Policy does not have a UnifiedUpdatePolicy to clear.") return true } // 2. Convert to a builder and clear the UnifiedUpdatePolicy field. val policyWithUucCleared = currentPolicy.toBuilder() .clearUnifiedUpdatePolicy() .build() // 3. Apply the modified Policy object. val updateRequest = UpdatePolicyRequest.builder() .setPolicy(policyWithUucCleared) .build() val updatedPolicy = policyClient.updatePolicy(updateRequest) return !updatedPolicy.hasUnifiedUpdatePolicy() } catch (e: Exception) { Log.e(TAG, "Error clearing policy: ${e.message}", e) return false } }
Java
import android.util.Log; import com.google.android.managementapi.policy.PolicyClient; import com.google.android.managementapi.policy.model.GetPolicyRequest; import com.google.android.managementapi.policy.model.Policy; import com.google.android.managementapi.policy.model.UpdatePolicyRequest; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; ListenableFutureclearUucPolicy(PolicyClient policyClient) { try { ListenableFuture currentPolicyFuture = policyClient.getPolicyFuture(GetPolicyRequest.builder().build()); return Futures.transformAsync(currentPolicyFuture, currentPolicy -> { if (!currentPolicy.hasUnifiedUpdatePolicy()) { Log.i(TAG, "Policy does not have a UnifiedUpdatePolicy to clear."); return Futures.immediateFuture(true); } Policy policyWithUucCleared = currentPolicy.toBuilder() .clearUnifiedUpdatePolicy() .build(); UpdatePolicyRequest updateRequest = UpdatePolicyRequest.builder() .setPolicy(policyWithUucCleared) .build(); ListenableFuture updateFuture = policyClient.updatePolicyFuture(updateRequest); return Futures.transform( updateFuture, updatedPolicy -> !updatedPolicy.hasUnifiedUpdatePolicy(), MoreExecutors.directExecutor() ); }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.e(TAG, "Error clearing policy: " + e.getMessage(), e); return Futures.immediateFuture(false); } }
ลำดับความสำคัญของ SystemUpdatePolicy ของ AOSP
ใน DPC ที่กำหนดเอง เอกสารนิยามความเข้ากันได้ของ Android (CDD) กำหนดให้อุปกรณ์ต้องปฏิบัติตาม SystemUpdatePolicy ของ AOSP ที่ตั้งค่าผ่าน DevicePolicyManager.setSystemUpdatePolicy
ด้วยเหตุนี้ ลักษณะการทำงานของการอัปเดต OTA ของ OEM จึงขึ้นอยู่กับว่า SystemUpdatePolicy ของ AOSP ทำงานอยู่ในอุปกรณ์หรือไม่
- ตั้งค่าทั้งนโยบาย UUC และ
SystemUpdatePolicyของ AOSP:SystemUpdatePolicyของ AOSP จะมีความสำคัญเหนือกว่าสำหรับการอัปเดต OTA ของ OEM และระบบจะไม่สนใจเป้าหมายOS_UPDATE_WITH_API_LEVEL_CHANGEและOS_UPDATE_WITHOUT_API_LEVEL_CHANGEของ UUC ล้างSystemUpdatePolicyของ AOSP ใน DPC ที่กำหนดเองหากต้องการให้ UUC จัดการการอัปเดต OTA ของ OEM - ตั้งค่านโยบาย UUC เท่านั้น (ล้าง AOSP
SystemUpdatePolicy): ตัวแทน OTA ของ OEM จะใช้นโยบาย UUC สำหรับการอัปเดต OTA ของ OEM ในอุปกรณ์ที่รองรับ - อุปกรณ์ที่ยังไม่รองรับ UUC สำหรับการอัปเดต OTA ของ OEM: ในอุปกรณ์ที่การรองรับ OTA ของ OEM ต้องใช้ Android 17 (ระดับ API 37) คุณสามารถใช้ UUC เพื่อควบคุมการอัปเดตระบบ Google Play (
GOOGLE_PLAY_SYSTEM_UPDATE) และบริการระบบของ Google (GOOGLE_SYSTEM_SERVICESและSINGLE_APP) ได้ในขณะที่ยังคงใช้ AOSPSystemUpdatePolicyสำหรับการอัปเดต OTA ของ OEM
คุณตรวจสอบได้ว่า SystemUpdatePolicy ของ AOSP ทำงานอยู่ในอุปกรณ์หรือไม่โดยใช้ DevicePolicyManager ดังนี้
Kotlin
import android.app.admin.DevicePolicyManager import android.content.Context fun Context.isSystemUpdatePolicyActive(): Boolean { val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as? DevicePolicyManager return dpm?.systemUpdatePolicy != null }
Java
import android.app.admin.DevicePolicyManager; import android.content.Context; boolean isSystemUpdatePolicyActive(Context context) { DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); return dpm != null && dpm.getSystemUpdatePolicy() != null; }
ตัวอย่างการกำหนดค่านโยบาย
ตัวอย่างต่อไปนี้แสดงวิธีสร้างกฎ UUC ใน Kotlin และ Java และนำไปใช้โดยใช้ตัวช่วย setUucPolicy ที่กำหนดไว้ในตั้งค่า ดึงข้อมูล และล้างนโยบายการอัปเดต ดูความหมายของแต่ละช่องได้ที่หัวข้อทำความเข้าใจนโยบาย UUC สถานการณ์เดียวกันนี้มีให้ใช้งานในรูปแบบ JSON ในการควบคุมการอัปเดตแบบรวม
บล็อกการอัปเดตระบบปฏิบัติการหลักในช่วงเวลาทำการ
กฎต่อไปนี้จะบล็อกการอัปเดตระบบปฏิบัติการหลัก (OS_UPDATE_WITH_API_LEVEL_CHANGE) ตั้งแต่เวลา 09:00 น. ถึง 17:00 น. ตั้งแต่วันจันทร์ถึงวันศุกร์
Kotlin
import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITH_API_LEVEL_CHANGE import java.time.DayOfWeek import java.time.LocalTime // 1. Define the target (OS update with API level change). val target = Target.builder() .setTargetType(OS_UPDATE_WITH_API_LEVEL_CHANGE) .build() // 2. Define the predicate (Monday through Friday, 09:00 to 17:00). val predicate = Predicate.builder() .setDaysOfWeek( listOf( DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY ) ) .setTimeOfDayLowerBound(LocalTime.of(9, 0)) .setTimeOfDayUpperBound(LocalTime.of(17, 0)) .build() // 3. Define the outcome (BLOCK). val outcome = Outcome.builder() .setOutcomeType(BLOCK) .build() // 4. Assemble and apply the rule. val rule = Rule.builder() .setTargets(listOf(target)) .setPredicate(predicate) .setOutcome(outcome) .setId("Block Policy") .build() setUucPolicy(policyClient, listOf(rule))
Java
import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITH_API_LEVEL_CHANGE; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target; import java.time.DayOfWeek; import java.time.LocalTime; import java.util.List; // 1. Define the target (OS update with API level change). Target target = Target.builder() .setTargetType(OS_UPDATE_WITH_API_LEVEL_CHANGE) .build(); // 2. Define the predicate (Monday through Friday, 09:00 to 17:00). Predicate predicate = Predicate.builder() .setDaysOfWeek( List.of( DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY ) ) .setTimeOfDayLowerBound(LocalTime.of(9, 0)) .setTimeOfDayUpperBound(LocalTime.of(17, 0)) .build(); // 3. Define the outcome (BLOCK). Outcome outcome = Outcome.builder() .setOutcomeType(BLOCK) .build(); // 4. Assemble and apply the rule. Rule rule = Rule.builder() .setTargets(List.of(target)) .setPredicate(predicate) .setOutcome(outcome) .setId("Block Policy") .build(); setUucPolicy(policyClient, List.of(rule));
บังคับให้อัปเดตระบบปฏิบัติการตามอายุการอัปเดต
กฎต่อไปนี้จะบังคับใช้การอัปเดตระบบปฏิบัติการหลัก (OS_UPDATE_WITH_API_LEVEL_CHANGE) โดยมีขอบเขตอายุการอัปเดตสูงสุด 7 วัน
Kotlin
import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.FORCE import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITH_API_LEVEL_CHANGE import java.time.Duration val target = Target.builder() .setTargetType(OS_UPDATE_WITH_API_LEVEL_CHANGE) .build() val predicate = Predicate.builder() .setUpdateAgeUpperBound(Duration.ofDays(7)) .build() val outcome = Outcome.builder() .setOutcomeType(FORCE) .build() val rule = Rule.builder() .setTargets(listOf(target)) .setPredicate(predicate) .setOutcome(outcome) .setId("Force Policy") .build() setUucPolicy(policyClient, listOf(rule))
Java
import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.FORCE; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITH_API_LEVEL_CHANGE; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target; import java.time.Duration; import java.util.List; Target target = Target.builder() .setTargetType(OS_UPDATE_WITH_API_LEVEL_CHANGE) .build(); Predicate predicate = Predicate.builder() .setUpdateAgeUpperBound(Duration.ofDays(7)) .build(); Outcome outcome = Outcome.builder() .setOutcomeType(FORCE) .build(); Rule rule = Rule.builder() .setTargets(List.of(target)) .setPredicate(predicate) .setOutcome(outcome) .setId("Force Policy") .build(); setUucPolicy(policyClient, List.of(rule));
บล็อกการอัปเดตสำหรับแอปบริการระบบของ Google แอปเดียว
หากต้องการควบคุมแพ็กเกจที่เฉพาะเจาะจงซึ่งเป็นส่วนหนึ่งของบริการของระบบ Google เช่น Android System WebView (com.google.android.webview) ให้ตั้งค่าประเภทเป้าหมายเป็น SINGLE_APP และระบุออบเจ็กต์ SingleApp พร้อมชื่อแพ็กเกจ ดังนี้
Kotlin
import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.SingleApp import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.SINGLE_APP import java.time.DayOfWeek import java.time.LocalTime val target = Target.builder() .setTargetType(SINGLE_APP) .setSingleApp( SingleApp.builder() .setPackageName("com.google.android.webview") .build() ) .build() val predicate = Predicate.builder() .setDaysOfWeek( listOf( DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY ) ) .setTimeOfDayLowerBound(LocalTime.of(9, 0)) .setTimeOfDayUpperBound(LocalTime.of(17, 0)) .build() val outcome = Outcome.builder() .setOutcomeType(BLOCK) .build() val rule = Rule.builder() .setTargets(listOf(target)) .setPredicate(predicate) .setOutcome(outcome) .setId("Block Webview Policy") .build() setUucPolicy(policyClient, listOf(rule))
Java
import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.SINGLE_APP; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.SingleApp; import java.time.DayOfWeek; import java.time.LocalTime; import java.util.List; Target target = Target.builder() .setTargetType(SINGLE_APP) .setSingleApp( SingleApp.builder() .setPackageName("com.google.android.webview") .build() ) .build(); Predicate predicate = Predicate.builder() .setDaysOfWeek( List.of( DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY ) ) .setTimeOfDayLowerBound(LocalTime.of(9, 0)) .setTimeOfDayUpperBound(LocalTime.of(17, 0)) .build(); Outcome outcome = Outcome.builder() .setOutcomeType(BLOCK) .build(); Rule rule = Rule.builder() .setTargets(List.of(target)) .setPredicate(predicate) .setOutcome(outcome) .setId("Block Webview Policy") .build(); setUucPolicy(policyClient, List.of(rule));
รวมกฎหลายข้อในเป้าหมายการอัปเดตทั้งหมด
เนื่องจากระบบจะประเมินกฎตามลำดับ คุณจึงรวมกฎหลายข้อเพื่อบล็อกการอัปเดตในช่วงเวลาที่เฉพาะเจาะจง (เช่น เวลาทำการหรือก่อนวันที่เป้าหมายในปฏิทิน) และบังคับให้อัปเดตนอกช่วงเวลาดังกล่าวได้
ตัวอย่างต่อไปนี้ใช้กฎตามลำดับ 2 ข้อกับเป้าหมายหมวดหมู่ทั้ง 4 รายการ (OS_UPDATE_WITH_API_LEVEL_CHANGE, OS_UPDATE_WITHOUT_API_LEVEL_CHANGE, GOOGLE_SYSTEM_SERVICES และ GOOGLE_PLAY_SYSTEM_UPDATE)
- บล็อกการอัปเดตทั้งหมดในช่วงเวลาทำการ (วันจันทร์-ศุกร์ เวลา 09:00 น. - 17:00 น.)
- นอกเวลาทำการ บังคับให้อัปเดตที่พร้อมใช้งานมาแล้วไม่เกิน 7 วัน
Kotlin
import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.FORCE import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.GOOGLE_PLAY_SYSTEM_UPDATE import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.GOOGLE_SYSTEM_SERVICES import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITHOUT_API_LEVEL_CHANGE import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITH_API_LEVEL_CHANGE import java.time.DayOfWeek import java.time.Duration import java.time.LocalTime // 1. Define the targets to reuse across both rules. val allTargets = listOf( Target.builder().setTargetType(OS_UPDATE_WITH_API_LEVEL_CHANGE).build(), Target.builder().setTargetType(OS_UPDATE_WITHOUT_API_LEVEL_CHANGE).build(), Target.builder().setTargetType(GOOGLE_SYSTEM_SERVICES).build(), Target.builder().setTargetType(GOOGLE_PLAY_SYSTEM_UPDATE).build() ) // 2. Rule 1: Block updates during business hours. val blockPredicate = Predicate.builder() .setDaysOfWeek( listOf( DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY ) ) .setTimeOfDayLowerBound(LocalTime.of(9, 0)) .setTimeOfDayUpperBound(LocalTime.of(17, 0)) .build() val blockOutcome = Outcome.builder() .setOutcomeType(BLOCK) .build() val rule1 = Rule.builder() .setTargets(allTargets) .setPredicate(blockPredicate) .setOutcome(blockOutcome) .setId("Block Policy - rule1") .build() // 3. Rule 2: Force updates within 7 days of availability. val forcePredicate = Predicate.builder() .setUpdateAgeUpperBound(Duration.ofDays(7)) .build() val forceOutcome = Outcome.builder() .setOutcomeType(FORCE) .build() val rule2 = Rule.builder() .setTargets(allTargets) .setPredicate(forcePredicate) .setOutcome(forceOutcome) .setId("Force Policy - rule2") .build() setUucPolicy(policyClient, listOf(rule1, rule2))
Java
import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.FORCE; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.GOOGLE_PLAY_SYSTEM_UPDATE; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.GOOGLE_SYSTEM_SERVICES; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITHOUT_API_LEVEL_CHANGE; import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target.TargetType.OS_UPDATE_WITH_API_LEVEL_CHANGE; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Target; import java.time.DayOfWeek; import java.time.Duration; import java.time.LocalTime; import java.util.List; // 1. Define the targets to reuse across both rules. ListallTargets = List.of( Target.builder().setTargetType(OS_UPDATE_WITH_API_LEVEL_CHANGE).build(), Target.builder().setTargetType(OS_UPDATE_WITHOUT_API_LEVEL_CHANGE).build(), Target.builder().setTargetType(GOOGLE_SYSTEM_SERVICES).build(), Target.builder().setTargetType(GOOGLE_PLAY_SYSTEM_UPDATE).build() ); // 2. Rule 1: Block updates during business hours. Predicate blockPredicate = Predicate.builder() .setDaysOfWeek( List.of( DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY ) ) .setTimeOfDayLowerBound(LocalTime.of(9, 0)) .setTimeOfDayUpperBound(LocalTime.of(17, 0)) .build(); Outcome blockOutcome = Outcome.builder() .setOutcomeType(BLOCK) .build(); Rule rule1 = Rule.builder() .setTargets(allTargets) .setPredicate(blockPredicate) .setOutcome(blockOutcome) .setId("Block Policy - rule1") .build(); // 3. Rule 2: Force updates within 7 days of availability. Predicate forcePredicate = Predicate.builder() .setUpdateAgeUpperBound(Duration.ofDays(7)) .build(); Outcome forceOutcome = Outcome.builder() .setOutcomeType(FORCE) .build(); Rule rule2 = Rule.builder() .setTargets(allTargets) .setPredicate(forcePredicate) .setOutcome(forceOutcome) .setId("Force Policy - rule2") .build(); setUucPolicy(policyClient, List.of(rule1, rule2));
จำกัดการอัปเดตจนถึงวันที่ในปฏิทิน
คุณสามารถใช้ setDateLowerBound และ setDateUpperBound ใน Predicate.Builder เพื่อจำกัดหรืออนุญาตการอัปเดตภายในช่วงวันที่ที่เฉพาะเจาะจงในปฏิทินตามเขตเวลาท้องถิ่นของอุปกรณ์ได้ ดังนี้
Kotlin
import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate import java.time.LocalDate val blockUntilDateRule = Rule.builder() .setId("block_until_date") .setTargets(allTargets) .setPredicate( Predicate.builder() .setDateUpperBound(LocalDate.of(2026, 3, 14)) .build() ) .setOutcome(Outcome.builder().setOutcomeType(BLOCK).build()) .build() setUucPolicy(policyClient, listOf(blockUntilDateRule))
Java
import static com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome.OutcomeType.BLOCK; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Outcome; import com.google.android.managementapi.policy.model.Policy.UnifiedUpdatePolicy.Rule.Predicate; import java.time.LocalDate; import java.util.List; Rule blockUntilDateRule = Rule.builder() .setId("block_until_date") .setTargets(allTargets) .setPredicate( Predicate.builder() .setDateUpperBound(LocalDate.of(2026, 3, 14)) .build() ) .setOutcome(Outcome.builder().setOutcomeType(BLOCK).build()) .build(); setUucPolicy(policyClient, List.of(blockUntilDateRule));
จัดการข้อผิดพลาด
หากการเรียก PolicyClient ไม่สำเร็จ DPC ที่กำหนดเองจะได้รับข้อยกเว้น (แสดงโดยตรงจากเมธอด Kotlin suspend getPolicy และ updatePolicy หรือรวมเป็นสาเหตุของ ExecutionException ใน getPolicyFuture และ updatePolicyFuture) ข้อยกเว้นที่พบบ่อยมีดังนี้
ApiLevelException: อุปกรณ์ใช้ Android เวอร์ชันต่ำกว่า Android 13 (ระดับ API 33)DeviceNotManagedException: อุปกรณ์ไม่ได้รับการจัดการเป็นอุปกรณ์ที่มีการจัดการครบวงจร (เจ้าของอุปกรณ์) หรืออุปกรณ์ของบริษัทที่มีโปรไฟล์งาน (COPE)AndroidDevicePolicyAppNotInstalledException,AndroidDevicePolicyAppDisabledExceptionหรือAndroidDevicePolicyAppNotUpdatedException: ไม่ได้ติดตั้งแอป ADP, แอปถูกปิดใช้ หรือใช้เวอร์ชันเก่าที่ไม่รองรับPolicyClientโทรหาprepareEnvironmentเพื่อติดตั้งหรืออัปเดตแอป ADPInvalidArgumentException: คำขอมีรูปแบบไม่ถูกต้องหรือมีกฎนโยบายที่ไม่ถูกต้อง (เช่น ละเว้นกฎidหรือใช้idซ้ำ ตั้งค่านาทีหรือวินาทีในขอบเขตช่วงเวลาของวัน ระบุระยะเวลาอายุการอัปเดตที่ไม่ใช่จำนวนเท่าของ 24 ชั่วโมง รวมถึงเป้าหมายที่ซ้ำกัน หรือตั้งค่าOutcomeType.DEFAULTอย่างชัดแจ้งในกฎ)SecurityException: แอปการโทรไม่ได้รับอนุญาตให้จัดการนโยบายด้านอุปกรณ์TimeoutException(java.util.concurrent.TimeoutException),InternalExceptionหรือคลาสย่อยอื่นๆ ของAmapiSdkException: เกิดข้อผิดพลาด IPC ชั่วคราวหรือข้อผิดพลาดภายในขณะสื่อสารกับแอป ADP ลองเรียกใช้ซ้ำโดยใช้กลยุทธ์ Exponential Backoff
กลยุทธ์การลองใหม่
สำหรับข้อยกเว้นที่เกิดจากสภาวะชั่วคราว (เช่น TimeoutException หรือ InternalException) ให้ใช้กลยุทธ์การลองใหม่ด้วย Exponential Backoff ดังนี้
- หลังจากดำเนินการไม่สำเร็จครั้งแรก ให้รอเป็นเวลา 5 วินาทีก่อนลองอีกครั้ง
- เพิ่มระยะเวลาหน่วงแบบทวีคูณในแต่ละครั้งที่พยายาม (10 วินาที, 20 วินาที และเพิ่มขึ้นเรื่อยๆ) จนถึงจำนวนครั้งสูงสุดที่พยายาม