ضبط "عناصر التحكّم الموحّدة في التحديثات" باستخدام حزمة تطوير البرامج (SDK) لواجهة برمجة التطبيقات Android Management API

يوضّح هذا الدليل كيفية استخدام حزمة تطوير البرامج (SDK) الخاصة بواجهة Android Management API في وحدة تحكّم مخصّصة بسياسة الجهاز (DPC) لضبط عناصر التحكّم الموحّدة في التحديثات (UUC) على الأجهزة المملوكة للشركة.

باستخدام حزمة تطوير البرامج (SDK) الخاصة بواجهة برمجة التطبيقات لإدارة Android، ترسل وحدة التحكّم في سياسة الجهاز (DPC) المخصّصة سياسة "الاستخدام غير المصنَّف" مباشرةً إلى تطبيق Android Device Policy على الجهاز. يقيّم ADP قواعد السياسة وفقًا لحالة الجهاز الحالية، ويوجّه Google Play وعميل OTA الخاص بالمصنّع الأصلي للجهاز بشأن كيفية التعامل مع التحديثات المعلّقة.

قبل البدء، يُرجى قراءة عناصر التحكّم الموحّدة في التحديثات للتعرّف على كيفية عمل القواعد والأهداف والمسندات والنتائج، والقيود التي تنطبق على جميع عمليات دمج عناصر التحكّم الموحّدة في التحديثات.

المتطلبات الأساسية

قبل دمج UUC في وحدة التحكّم في السياسات على الجهاز (DPC) المخصّصة، تأكَّد من استيفاء المتطلبات التالية:

الدمج مع حزمة تطوير البرامج (SDK) لواجهة برمجة التطبيقات Android Management API في وحدة التحكّم بسياسة الجهاز (DPC) المخصّصة

لضبط سياسة UUC على جهاز، يجب دمج وحدة التحكّم بسياسة الجهاز (DPC) المخصّصة مع حزمة تطوير البرامج (SDK) لواجهة برمجة التطبيقات Android Management API. للحصول على تعليمات حول إضافة المكتبة وضبط ملف بيان تطبيقك، يُرجى الاطّلاع على دليل دمج حزمة تطوير البرامج (SDK) لواجهة برمجة التطبيقات Android Management API.

خطوات ضبط "عناصر التحكّم الموحّدة في التحديثات"

لضبط سياسات 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
}

جافا

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()، يتم تثبيت تطبيق ADP تلقائيًا من خلال prepareEnvironment (إذا لم يكن مثبّتًا من قبل) ويتم تحديث تطبيق ADP و"متجر Google Play" بدون تفاعل المستخدم. لمزيد من المعلومات حول إعداد البيئة في مسارات "وحدة التحكّم بسياسة الجهاز" المخصّصة، يُرجى الاطّلاع على إعداد البيئة وتسجيل المستخدمين.

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
}

جافا

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
    }
}

جافا

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)
    }
}

جافا

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
    }
}

جافا

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 في نظام التشغيل Android مفتوح المصدر (AOSP)

في وحدة التحكّم بسياسة الجهاز (DPC) المخصّصة، يتطلّب مستند تعريف معايير التوافق (CDD) مع Android من الأجهزة الالتزام بإعدادات SystemUpdatePolicy في مشروع Android المفتوح المصدر (AOSP) من خلال DevicePolicyManager.setSystemUpdatePolicy.

نتيجةً لذلك، يعتمد سلوك تحديثات OTA من المصنّع الأصلي للجهاز على ما إذا كان SystemUpdatePolicy من مشروع Android المفتوح المصدر (AOSP) نشطًا على الجهاز:

  • في حال ضبط كل من سياسة UUC وAOSP SystemUpdatePolicy: تكون الأولوية لـ AOSP SystemUpdatePolicy في ما يتعلّق بالتحديثات عبر اتصال لاسلكي التي يجريها المصنّع الأصلي للجهاز، ويتم تجاهل استهدافات UUC OS_UPDATE_WITH_API_LEVEL_CHANGE وOS_UPDATE_WITHOUT_API_LEVEL_CHANGE. يجب محو إعدادات AOSP SystemUpdatePolicy في وحدة التحكّم بسياسة الجهاز المخصّصة إذا أردت أن تدير وحدة التحكّم في التحديثات تحديثات المصنّع الأصلي للجهاز عبر اتصال لاسلكي.
  • ضبط سياسة UUC فقط (تم محو سياسة SystemUpdatePolicy في مشروع Android المفتوح المصدر): يطبّق وكيل التحديثات عبر اتصال لاسلكي من المصنّع الأصلي للجهاز سياسة UUC على التحديثات عبر اتصال لاسلكي من المصنّع الأصلي للجهاز على الأجهزة المتوافقة.
  • الأجهزة التي لا تتيح بعد استخدام UUC لتحديثات OTA من المصنّع الأصلي للجهاز: على الأجهزة التي يتطلّب فيها تحديث OTA من المصنّع الأصلي للجهاز استخدام Android 17 (المستوى 37 من واجهة برمجة التطبيقات)، يمكنك استخدام UUC للتحكّم في تحديثات نظام Google Play (GOOGLE_PLAY_SYSTEM_UPDATE) وخدمات نظام Google (GOOGLE_SYSTEM_SERVICES وSINGLE_APP) مع مواصلة استخدام AOSP SystemUpdatePolicy لتحديثات OTA من المصنّع الأصلي للجهاز.

يمكنك التحقّق مما إذا كان ملف شخصي SystemUpdatePolicy في نظام Android المفتوح المصدر (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
}

جافا

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))

جافا

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))

جافا

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))

جافا

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));

دمج قواعد متعددة في جميع أهداف التعديل

بما أنّه يتم تقييم القواعد بالترتيب، يمكنك دمج قواعد متعددة لحظر التحديثات خلال فترات زمنية محدّدة (مثل ساعات العمل أو قبل تاريخ مستهدف في التقويم) وفرض التحديثات خارج هذه الفترات الزمنية.

يطبّق المثال التالي قاعدتَين متتاليتَين على جميع الفئات المستهدَفة الأربع (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))

جافا

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))

جافا

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 (المستوى 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. أعِد محاولة الاتصال باستخدام استراتيجية التراجع الأسي.

استراتيجيات إعادة المحاولة

بالنسبة إلى الاستثناءات الناتجة عن حالة عابرة (مثل TimeoutException أو InternalException)، يمكنك تنفيذ استراتيجية إعادة المحاولة باستخدام خوارزمية الرقود الأسي الثنائي:

  1. بعد حدوث الخطأ الأول، انتظِر لمدة 5 ثوانٍ قبل إعادة المحاولة.
  2. يمكنك زيادة مدة التأخير بشكل كبير في كل محاولة لاحقة (10 ثوانٍ، 20 ثانية، وما إلى ذلك) حتى الوصول إلى الحد الأقصى لعدد المحاولات.