إدارة تحديثات النظام

يوضّح دليل المطوّر هذا كيف يمكن لوحدة التحكّم بسياسة الجهاز (DPC) إدارة تحديثات نظام Android نيابةً عن مستخدم الجهاز.

المقدّمة

يمكن لأجهزة Android تلقّي تحديثات عبر شبكة غير سلكيّة (OTA) وتثبيتها على النظام وبرامج التطبيقات. يرسل Android إشعارًا إلى مستخدم الجهاز يفيد بتوفّر تحديث للنظام، وأنّه يمكن لمستخدم الجهاز تثبيت التحديث على الفور أو لاحقًا.

يمكن لمشرف تكنولوجيا المعلومات إدارة تحديثات النظام لمستخدم الجهاز باستخدام وحدة التحكّم بسياسة الجهاز. يمكن لوحدات التحكّم بسياسة الجهاز (DPC) امتلاك جهاز مُدار بالكامل (يُسمى مالك الجهاز) أو امتلاك ملف شخصي للعمل (يُسمى مالك الملف الشخصي). يوضح الجدول 1 كيف يمكن لمالكي الأجهزة إدارة تحديثات النظام، بينما يمكن لمالكي الملفات الشخصية الإبلاغ فقط عن المعلومات المتعلقة بتحديثات النظام.

الجدول 1: تعتمد المهام المتاحة لوحدات التحكّم بسياسة الجهاز (DPC) على وضع المالك

المهمة مالك الجهاز مالك الملف الشخصي
التأكّد من توفّر تحديثات للنظام في انتظار المراجعة
تلقّي معاودة الاتصال عند توفّر تحديثات النظام الجديدة
ضبط سياسة تحديث محلي للتحكُّم في وقت تثبيت Android لتحديثات النظام
تجميد إصدار نظام التشغيل خلال الفترات الحرجة

البحث عن تحديثات في انتظار التثبيت

التحديث المعلَّق هو تحديث النظام لجهاز لم يتم تثبيته بعد. يمكن لوحدة التحكّم بسياسة الجهاز مساعدة مشرفي تكنولوجيا المعلومات في معرفة الأجهزة التي تتضمن تحديثات نظام معلّقة، وربما توجيه طلب إلى مستخدمي الأجهزة بتثبيت التحديثات المهمة على الفور.

يستطيع مالكو الأجهزة ومالكي الملفات الشخصية التي تعمل بالإصدار Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث التحقّق مما إذا كان هناك تحديث نظام في انتظار المراجعة. الاتصال برقم DevicePolicyManager.getPendingSystemUpdate() الذي يعرض الرقم null إذا كان الجهاز محدَّثًا. إذا كان هناك تحديث للنظام في انتظار المراجعة، تعرض الطريقة معلومات حول التحديث.

الاطّلاع على مزيد من المعلومات عن التحديث في انتظار المراجعة

بعد طلب رمز التحديث getPendingSystemUpdate()، يمكنك فحص قيمة SystemUpdateInfo التي تم إرجاعها لمعرفة المزيد من المعلومات عن التحديث المعلّق. ويوضّح المثال التالي كيفية معرفة وقت توفّر تحديث معلّق لأول مرة للجهاز:

Kotlin

val firstAvailable =
        dpm.getPendingSystemUpdate(adminName)?.receivedTime
firstAvailable?.let {
    Log.i(TAG, "Update first available: ${Date(firstAvailable)}")
}

Java

SystemUpdateInfo updateInfo = dpm.getPendingSystemUpdate(adminName);
if (updateInfo != null) {
  Long firstAvailable = updateInfo.getReceivedTime();
  Log.i(TAG, "Update first available: " + new Date(firstAvailable));
}

عمليات معاودة الاتصال بالنظام

عندما يتوفّر تحديث، يرسل نظام Android إشعارًا إلى مالكي الأجهزة بشأن التحديث الجديد. في الإصدار Android 8.0 أو الإصدارات الأحدث، يرسل النظام إشعارات إلى مالكي الملفات التجارية أيضًا.

في فئة DeviceAdminReceiver الفرعية، يمكنك إلغاء استدعاء onSystemUpdatePending(). ولست بحاجة إلى التسجيل أو الإعلان عن وحدة التحكّم بسياسة الجهاز (DPC) لتلقّي معاودة الاتصال. قد يستدعي النظام هذه الطريقة أكثر من مرة لإجراء تحديث واحد، لذا عليك التحقّق من حالة التحديث قبل الاستجابة. يمكنك الاتصال بـ getPendingSystemUpdate() لمعرفة المزيد حول تحديث النظام في معاودة الاتصال. يوضّح المثال التالي كيفية إجراء ذلك:

Kotlin

/**
 * Called when a new update is available.
 */
override fun onSystemUpdatePending(context: Context?, intent: Intent?,
                                   receivedTime: Long) {

    // System update information is supported in API level 26 or higher.
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        return
    }

    val updateInfo = getManager(context)
            .getPendingSystemUpdate(getWho(context))
            ?: return
    if (updateInfo.securityPatchState ==
            SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE) {
        // Perhaps install because this is a security patch.
        // ...
    }
}

Java

/**
 * Called when a new update is available.
 */
public void onSystemUpdatePending (Context context, Intent intent,
                                   long receivedTime) {

  // System update information is supported in API level 26 or higher.
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    return;
  }
  SystemUpdateInfo updateInfo = getManager(context)
      .getPendingSystemUpdate(getWho(context));
  if (updateInfo == null) {
    return;
  }
  if (updateInfo.getSecurityPatchState() ==
      SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE) {
    // Perhaps install because this is a security patch.
    // ...
  }
}

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

تعديل السياسات

يمكن لمالك الجهاز التحكّم في وقت تثبيت التحديثات من خلال ضبط سياسة تحديث للنظام المحلي على الجهاز. يمكن أن تكون سياسة تحديث النظام من بين ثلاثة أنواع:

تلقائي
يثبّت تحديثات النظام بمجرد توفّرها (بدون تفاعل المستخدم). يؤدي ضبط هذا النوع من السياسات إلى تثبيت أي تحديثات في انتظار المراجعة قد يتم تأجيلها أو انتظار فترة صيانة.
مع نافذ
يثبّت تحديثات النظام أثناء نافذة الصيانة اليومية (بدون تفاعل المستخدم). حدِّد بداية ونهاية نافذة الصيانة اليومية كدقائق من اليوم عند إنشاء سياسة نافذة جديدة.
مؤجلة
تأجيل تثبيت تحديثات النظام لمدة 30 يومًا بعد انتهاء الفترة البالغة 30 يومًا، يطلب النظام من مستخدم الجهاز تثبيت التحديث.

فترات التأجيل

يفرض النظام قيودًا على عملية التحديث لمدة 30 يومًا كحدّ أقصى. تبدأ الفترة عندما يؤجل النظام التحديث لأول مرة، ولن يؤدي وضع سياسات تأجيل جديدة إلى تمديد الفترة.

بالإضافة إلى التأجيل، قد لا يتمكن نظام Android من تثبيت تحديث لأسباب أخرى، مثل عدم الاتصال بالإنترنت أو عدم كفاية مساحة القرص أو انخفاض طاقة البطارية.

ويعيد النظام ضبط موقّت التأجيل لمدة 30 يومًا في حال توفّر تحديث مختلف خلال تلك الفترة، ما يمنح مشرفي تكنولوجيا المعلومات الفرصة لتجربة تحديثات النظام المجمّعة. بعد مرور 30 يومًا بدون تحديث جديد، يطلب النظام من المستخدم تثبيت جميع التحديثات المعلّقة. لاحقًا، عندما يتوفر تحديث جديد للنظام، تبدأ الفترة البالغة 30 يومًا مرة أخرى.

كيفية ضبط سياسة

يمكنك ضبط سياسات التحديث في الإصدار Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث. لتحديد الوقت الذي يجب أن يثبّت فيه الجهاز تحديثات النظام، يمكنك إنشاء مثيل SystemUpdatePolicy باستخدام أحد الأنواع الثلاثة الموضّحة أعلاه. لضبط سياسة، يطلب مالك الجهاز استخدام طريقة DevicePolicyManager setSystemUpdatePolicy(). يوضح نموذج التعليمات البرمجية التالي كيف يمكنك القيام بذلك. للاطّلاع على مثال لسياسة النوافذ، راجِع مستندات SystemUpdatePolicy.

Kotlin

// Create the system update policy to postpone installation for 30 days.
val policy = SystemUpdatePolicy.createPostponeInstallPolicy()

// Get a DevicePolicyManager instance to set the policy on the device.
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
val adminName = getComponentName(context)

// Set the policy.
dpm.setSystemUpdatePolicy(adminName, policy)

Java

// Create the system update policy to postpone installation for 30 days.
SystemUpdatePolicy policy = SystemUpdatePolicy.createPostponeInstallPolicy();

// Get a DevicePolicyManager instance to set the policy on the device.
DevicePolicyManager dpm = (DevicePolicyManager) context
    .getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminName = getComponentName(context);

// Set the policy.
dpm.setSystemUpdatePolicy(adminName, policy);

لا يمكن تغيير مثيلات السياسات بعد إنشائها. ولتغييرها عند تثبيت أحد الأجهزة للتحديثات، يمكنك إنشاء سياسة جديدة وضبطها. لإزالة سياسة من جهاز، عليك استدعاء setSystemUpdatePolicy() مع تمرير null كوسيطة policy. بعد إزالة وحدة التحكّم بسياسة الجهاز (DPC) لإحدى السياسات، ستظهر لمستخدم الجهاز إشعارات بشأن أي تحديثات متوفرة للنظام.

يمكن للتطبيقات الاتصال بالرقم getSystemUpdatePolicy() للحصول على السياسة الحالية للجهاز. وإذا عرضت هذه الطريقة القيمة null، يعني ذلك أنّه لم يتم ضبط سياسة في الوقت الحالي.

فترات إيقاف التحديثات

لتجميد إصدار نظام التشغيل خلال الفترات المهمة، مثل العطلات أو أوقات الانشغال الأخرى، يمكن لمالكي الأجهزة تعليق تحديثات النظام لمدة تصل إلى 90 يومًا. عندما يكون الجهاز في فترة التوقف عن العمل، يعمل على النحو التالي:

  • لن يتلقّى الجهاز أي إشعارات بشأن تحديثات النظام التي في انتظار المراجعة.
  • لم يتم تثبيت تحديثات النظام على نظام التشغيل.
  • لا يمكن لمستخدمي الأجهزة البحث يدويًا عن تحديثات النظام من خلال الإعدادات.

ويفرض النظام فترة تخزين احتياطية إلزامية تبلغ 60 يومًا بعد أي فترات محددة للتجميد لمنع تجميد الجهاز إلى أجل غير مسمى. وتذكر أن تجميد تحديثات النظام يمكن أن يمنع الأجهزة من تلقي تحديثات مهمة.

الشكل 1. تم ضبط فترتين لإيقاف التحديثات لجهاز
تقويم يعرض فترتين لإيقاف التحديثات في السنة بفترة احتياطية تبلغ 60 يومًا.

يمكنك ضبط فترات لإيقاف التحديثات في سياسة تحديث. ولا يمكنك ضبط فترات إيقاف التحديثات بدون ضبط سياسة عندما لا يكون الجهاز في فترة من الفترات التي تحددها لإيقاف التحديثات، يسري السلوك العادي للسياسة (سواء كان يعمل تلقائيًا أو محدَّدًا بالنافذة أو مؤجلة).

كيفية ضبط فترة إيقاف التحديثات

يمكنك ضبط فترات لإيقاف التحديثات في Android 9 (المستوى 28 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث. يضبط مالك الجهاز فترة إيقاف السياسة وفقًا لسياسة تحديث النظام قبل ضبط السياسة للجهاز. الخطوات هي:

  1. أنشئ سياسة جديدة (أو احصل على السياسة الحالية) لتحديث النظام.
  2. يمكنك ضبط فترات إيقاف التحديثات في السياسة من خلال طلب الرقم setFreezePeriods().
  3. لضبط السياسة وفترات إيقاف الجهاز، يُرجى الاتصال على setSystemUpdatePolicy().

نظرًا لأن فترة التجميد تتكرر سنويًا، يتم تمثيل تاريخي البدء والانتهاء للفترة بقيم الشهر واليوم. يجب أن يبدأ يوم البدء بعد 60 يومًا على الأقل من انتهاء أي فترة تجميد سابقة. ويوضّح المثال التالي كيفية ضبط فترتين لإيقاف التحديثات لسياسة تحديث نظام حالية:

Kotlin

// Get the existing policy from the DevicePolicyController instance.
val policy = dpm.systemUpdatePolicy ?: return

try {
    // Set the two annual freeze periods on the policy for our retail
    // point-of-sale devices.
    val summerSale = FreezePeriod(
            MonthDay.of(6, 1),
            MonthDay.of(7, 31)) // Jun 1 - Jul 31 inclusive
    val winterSale = FreezePeriod(
            MonthDay.of(11, 20),
            MonthDay.of(1, 12)) // Nov 20 - Jan 12 inclusive
    policy.freezePeriods = Arrays.asList(summerSale, winterSale)

    // Set the policy again to activate the freeze periods.
    dpm.setSystemUpdatePolicy(adminName, policy)

} catch (e: SystemUpdatePolicy.ValidationFailedException) {
    // There must be previous periods recorded on the device because
    // summerSale and winterSale don’t overlap and are separated by more
    // than 60 days. Report the overlap ...
}

Java

// Get the existing policy from the DevicePolicyController instance.
SystemUpdatePolicy policy = dpm.getSystemUpdatePolicy();

try {
  // Set the two annual freeze periods on the policy for our
  // retail point-of-sale devices.
  FreezePeriod summerSale = new FreezePeriod(
      MonthDay.of(6, 1),
      MonthDay.of(7, 31)); // Jun 1 - Jul 31 inclusive
  FreezePeriod winterSale = new FreezePeriod(
      MonthDay.of(11, 20),
      MonthDay.of(1, 12)); // Nov 20 - Jan 12 inclusive
  policy.setFreezePeriods(Arrays.asList(summerSale, winterSale));

  // Don’t forget to set the policy again to activate the freeze periods.
  dpm.setSystemUpdatePolicy(adminName, policy);

} catch (SystemUpdatePolicy.ValidationFailedException e) {
  // There must be previous periods recorded on the device because summerSale
  // and winterSale don’t overlap and are separated by more than 60 days.
  // Report the overlap ...
}

يشمل كل من يوم البدء ويوم الانتهاء. إذا كان يوم البدء أكبر من يوم الانتهاء (مثل winterSale في المثال السابق)، تمتد فترة التجميد إلى العام التالي.

عند تحديد فترات لإيقاف التحديثات في سياسة تحديث النظام، يختبر Android المتطلبات التالية:

  • عدم تجاوز مدة الإيقاف 90 يومًا.
  • تبلغ الفترة بين فترات إيقاف التحديثات 60 يومًا على الأقل.
  • لا تتداخل فترات إيقاف التحديثات.
  • لا تتوفّر فترات إيقاف متكرّرة.

عند ضبط سياسة تحديث النظام لأحد الأجهزة، يكرر Android هذه الاختبارات ويتضمن أي فترات حالية أو سابقة لإيقاف تشغيل الجهاز.

يطرح Android علامة SystemUpdatePolicy.ValidationFailedException عند تعذُّر إجراء أي من هذه الاختبارات.

للحصول على قائمة بفترات إيقاف التحديثات التي تم ضبطها سابقًا في عنصر سياسة تحديث النظام، يمكن لجميع التطبيقات المثبّتة استدعاء الإجراء SystemUpdatePolicy.getFreezePeriods(). يستدعي المثال التالي هذه الطريقة لتسجيل فترات تجميد الجهاز:

Kotlin

// Log any freeze periods that might be set on a system update policy.
dpm.systemUpdatePolicy?.freezePeriods?.forEach {
    Log.i(TAG, "Freeze period: $it")
}

Java

// Log any freeze periods that might be set on a system update policy.
SystemUpdatePolicy currentPolicy = dpm.getSystemUpdatePolicy();
if (currentPolicy != null) { // A policy might not be set.
  for (FreezePeriod freezePeriod : currentPolicy.getFreezePeriods()) {
    Log.i(TAG, "Freeze period: " + freezePeriod.toString());
  }
}

السنوات الكبيسة

يستخدم Android تقويم ISO 8601 (يسمى أيضًا التقويم الميلادي) لحساب فترات التجميد ويتجاهل السنوات الكبيسة. هذا يعني أنه لم يتم التعرف على 29 فبراير كتاريخ صالح ويتم التعامل معه كما لو كان 28 فبراير. لذلك، لا يتم احتساب يوم 29 شباط (فبراير) عند حساب مدة التجميد.

التطوير والاختبار

أثناء تطوير واختبار ميزة تحديث نظام وحدة التحكّم بسياسة الجهاز (DPC)، قد تحتاج إلى إنشاء عدة فترات لإيقاف التحديثات. ونظرًا لأن Android يتحقق من وجود فاصل زمني مدته 60 يومًا بين الفترات السابقة لإيقاف التحديثات، قد لا تتمكن من تحديد فترة تجميد جديدة بدون محو سجلّ الفترات السابقة أولاً. لمحو سجلّ فترة تجميد الجهاز، شغِّل الأمر التالي في واجهة أوامر Android Debug Bridge (adb):

adb shell dpm clear-freeze-period-record

يمكنك التأكّد من أنّ الجهاز في فترة التوقف عن العمل من خلال التحقّق من إيقاف واجهة المستخدم الخاصة بتحديثات النظام.

مراجع إضافية

لمعرفة المزيد من المعلومات عن تحديثات النظام، يُرجى الاطّلاع على مستندات تحديثات التحديث عبر الهواء لمشروع Android مفتوح المصدر.