กำหนดค่าการควบคุมการอัปเดตแบบรวมด้วย AMAPI SDK

คู่มือนี้อธิบายวิธีใช้ Android Management API (AMAPI) SDK ในเครื่องมือควบคุมนโยบายด้านอุปกรณ์ (DPC) ที่กำหนดเองเพื่อกำหนดค่าการควบคุมการอัปเดตแบบรวม (UUC) ในอุปกรณ์ของบริษัท

เมื่อใช้ AMAPI SDK แล้ว DPC ที่กำหนดเองจะส่งนโยบาย UUC ไปยังแอป Android Device Policy (ADP) ในอุปกรณ์โดยตรง ADP จะประเมินกฎนโยบายเทียบกับสถานะปัจจุบันของอุปกรณ์ และแนะนำ Google Play และไคลเอ็นต์ OTA ของ OEM เกี่ยวกับวิธีจัดการการอัปเดตที่รอดำเนินการ

ก่อนเริ่มต้น โปรดอ่านการควบคุมการอัปเดตแบบรวมเพื่อดูวิธีการทำงานของกฎ เป้าหมาย เพรดิเคต และผลลัพธ์ รวมถึงข้อจำกัดที่ใช้กับการผสานรวม UUC ทั้งหมด

ข้อกำหนดเบื้องต้น

ก่อนผสานรวม UUC เข้ากับ DPC ที่กำหนดเอง ให้ตรวจสอบข้อกำหนดต่อไปนี้

ผสานรวมกับ AMAPI SDK ใน DPC ที่กำหนดเอง

หากต้องการกำหนดค่านโยบาย UUC ในอุปกรณ์ DPC ที่กำหนดเองต้องผสานรวมกับ AMAPI SDK ดูวิธีการเพิ่มไลบรารีและกำหนดค่าไฟล์ Manifest ของแอปได้ที่คู่มือการผสานรวม AMAPI SDK

ขั้นตอนในการกำหนดค่าการควบคุมการอัปเดตแบบรวม

หากต้องการกำหนดค่านโยบาย UUC จาก DPC ที่กำหนดเอง ให้ตรวจสอบว่าสภาพแวดล้อมของไคลเอ็นต์ในอุปกรณ์พร้อมใช้งานและเป็นเวอร์ชันล่าสุดก่อนส่งคำขอนโยบายไปยัง ADP โดยทำดังนี้

  1. ยืนยันสภาพแวดล้อมของไคลเอ็นต์
  2. เตรียมสภาพแวดล้อมของไคลเอ็นต์
  3. ตั้งค่า ดึงข้อมูล และล้างนโยบายการอัปเดต

ยืนยันสภาพแวดล้อมของไคลเอ็นต์

ตัวอย่างต่อไปนี้แสดงวิธีเรียกใช้ 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 {
        ImmutableList roles = 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 {
        ImmutableList roles = 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;

ListenableFuture setUucPolicy(
        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();
        ListenableFuture getActivePolicy =
                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;

ListenableFuture clearUucPolicy(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) ได้ในขณะที่ยังคงใช้ AOSP SystemUpdatePolicy สำหรับการอัปเดต 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)

  1. บล็อกการอัปเดตทั้งหมดในช่วงเวลาทำการ (วันจันทร์-ศุกร์ เวลา 09:00 น. - 17:00 น.)
  2. นอกเวลาทำการ บังคับให้อัปเดตที่พร้อมใช้งานมาแล้วไม่เกิน 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.
List allTargets = 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 เพื่อติดตั้งหรืออัปเดตแอป ADP
  • InvalidArgumentException: คำขอมีรูปแบบไม่ถูกต้องหรือมีกฎนโยบายที่ไม่ถูกต้อง (เช่น ละเว้นกฎ id หรือใช้ id ซ้ำ ตั้งค่านาทีหรือวินาทีในขอบเขตช่วงเวลาของวัน ระบุระยะเวลาอายุการอัปเดตที่ไม่ใช่จำนวนเท่าของ 24 ชั่วโมง รวมถึงเป้าหมายที่ซ้ำกัน หรือตั้งค่า OutcomeType.DEFAULT อย่างชัดแจ้งในกฎ)
  • SecurityException: แอปการโทรไม่ได้รับอนุญาตให้จัดการนโยบายด้านอุปกรณ์
  • TimeoutException (java.util.concurrent.TimeoutException), InternalException หรือคลาสย่อยอื่นๆ ของ AmapiSdkException: เกิดข้อผิดพลาด IPC ชั่วคราวหรือข้อผิดพลาดภายในขณะสื่อสารกับแอป ADP ลองเรียกใช้ซ้ำโดยใช้กลยุทธ์ Exponential Backoff

กลยุทธ์การลองใหม่

สำหรับข้อยกเว้นที่เกิดจากสภาวะชั่วคราว (เช่น TimeoutException หรือ InternalException) ให้ใช้กลยุทธ์การลองใหม่ด้วย Exponential Backoff ดังนี้

  1. หลังจากดำเนินการไม่สำเร็จครั้งแรก ให้รอเป็นเวลา 5 วินาทีก่อนลองอีกครั้ง
  2. เพิ่มระยะเวลาหน่วงแบบทวีคูณในแต่ละครั้งที่พยายาม (10 วินาที, 20 วินาที และเพิ่มขึ้นเรื่อยๆ) จนถึงจำนวนครั้งสูงสุดที่พยายาม