إعداد عمليات الضبط المُدارة

إذا كنت تطوّر تطبيقات لسوق المؤسسات، قد تحتاج إلى استيفاء متطلبات معيّنة تحدّدها سياسات المؤسسة. تسمح عمليات الضبط المُدارة، التي كانت تُعرف سابقًا باسم قيود التطبيقات، لمشرف تكنولوجيا المعلومات في المؤسسة بتحديد الإعدادات للتطبيقات عن بُعد. وتُعدّ هذه الميزة مفيدة بشكل خاص للتطبيقات التي وافقت عليها المؤسسة والتي تم نشرها في ملف عمل.

على سبيل المثال، قد تطلب المؤسسة من التطبيقات الموافَق عليها السماح لمدير تكنولوجيا المعلومات بما يلي:

  • السماح بعناوين URL أو حظرها لمتصفّح ويب
  • ضبط ما إذا كان يُسمح للتطبيق بمزامنة المحتوى عبر شبكة الجوّال أو عبر شبكة Wi-Fi فقط
  • ضبط إعدادات البريد الإلكتروني للتطبيق

يوضّح هذا الدليل كيفية تنفيذ إعدادات الضبط المُدار في تطبيقك. للاطّلاع على نماذج التطبيقات التي تتضمّن إعدادات مُدارة، يُرجى الاطّلاع على ManagedConfigurations. إذا كنت مطوّرًا لخدمات إدارة الخدمات الجوّالة للمؤسسات (EMM)، يمكنك الرجوع إلى دليل Android Management API.

ملاحظة: لأسباب تاريخية، تُعرف إعدادات الضبط هذه باسم القيود، ويتم تنفيذها باستخدام الملفات والفئات التي تستخدِم هذا المصطلح (مثل RestrictionsManager). ومع ذلك، يمكن أن تنفِّذ هذه القيود مجموعة كبيرة من خيارات الضبط، وليس فقط القيود المفروضة على وظائف التطبيق.

نظرة عامة على الإعداد عن بُعد

تحدِّد التطبيقات خيارات الضبط المُدار التي يمكن لمشرف تكنولوجيا المعلومات ضبطها عن بُعد. هذه هي الإعدادات العشوائية التي يمكن تغييرها من قِبل مقدّم الضبط المُدار. إذا كان تطبيقك قيد التشغيل في ملف عمل، يمكن لمشرف تكنولوجيا المعلومات تغيير الإعدادات المُدارة لتطبيقك.

مقدّم الإعدادات المُدارة هو تطبيق آخر يعمل على الجهاز نفسه. يتم عادةً التحكّم في هذا التطبيق من قِبل مشرف تكنولوجيا المعلومات. يُرسِل مشرف تكنولوجيا المعلومات تغييرات الإعدادات إلى تطبيق مقدّم الإعدادات المُدار. ويغيّر هذا التطبيق بدوره الإعدادات في تطبيقك.

لتوفير عمليات ضبط مُدارة خارجيًا:

  • حدِّد الإعدادات المُدارة في بيان التطبيق. يسمح ذلك لمشرف تكنولوجيا المعلومات بقراءة إعدادات التطبيق من خلال واجهات برمجة تطبيقات Google Play.
  • عند استئناف تشغيل التطبيق، استخدِم عنصر RestrictionsManager للتحقّق من الإعدادات المُدارة الحالية، وغيِّر واجهة المستخدم وسلوك تطبيقك لتتوافق مع تلك الإعدادات.
  • استمع إلى نية ACTION_APPLICATION_RESTRICTIONS_CHANGED. عند تلقّي هذا البث، ضَع علامة في المربّع RestrictionsManager للاطّلاع على الإعدادات المُدارة الحالية، وأدخِل أي تغييرات ضرورية على سلوك تطبيقك.

تحديد عمليات الضبط المُدارة

يمكن أن يتيح تطبيقك أي إعداد مُدار تريد تحديده. يمكنك الإفصاح عن الإعدادات المُدارة للتطبيق في ملف الإعدادات المُدارة، والإفصاح عن ملف الإعدادات في البيان. يتيح إنشاء ملف الإعدادات للتطبيقات الأخرى فحص عمليات الضبط المُدارة التي يوفّرها تطبيقك. يمكن لشركاء إدارة الخدمات الجوّالة للمؤسسات قراءة إعدادات تطبيقك باستخدام واجهات برمجة تطبيقات Google Play.

لتحديد خيارات الضبط عن بُعد لتطبيقك، ضَع العنصر التالي في عنصر <application> في البيان:

<meta-data android:name="android.content.APP_RESTRICTIONS"
    android:resource="@xml/app_restrictions" />

أنشئ ملفًا باسم app_restrictions.xml في دليل res/xml الخاص بتطبيقك. يتم وصف بنية هذا الملف في المرجع الخاص بـ RestrictionsManager. يحتوي الملف على عنصر <restrictions> واحد من المستوى الأعلى يحتوي بدوره على عنصر <restriction> ثانوي واحد لكل خيار من خيارات الضبط التي يتضمّنها التطبيق.

ملاحظة: لا تنشئ نُسخًا مترجَمة منملف الضبط المُدار. لا يُسمح لتطبيقك إلا باستخدام ملف إعدادات مُدار واحد، وبالتالي ستكون الإعدادات متسقة لتطبيقك في جميع اللغات.

في بيئة المؤسسة، ستستخدم خدمة "إدارة الخدمات الجوّالة للمؤسسات" عادةً مخطّط الضبط المُدار لإنشاء وحدة تحكّم عن بُعد لمشرفي تكنولوجيا المعلومات، حتى يتمكّن المشرفون من ضبط تطبيقك عن بُعد.

يمكن لموفّر الإعدادات المُدارة طلب معلومات من التطبيق للعثور على تفاصيل عن الإعدادات المتاحة للتطبيق، بما في ذلك نص وصفها. يمكن لموفّر الإعدادات ومشرف تكنولوجيا المعلومات تغيير الإعدادات المُدارة لتطبيقك في أي وقت، حتى إذا لم يكن التطبيق قيد التشغيل.

على سبيل المثال، لنفترض أنّه يمكن ضبط تطبيقك عن بُعد للسماح له أو منعه من تنزيل البيانات عبر اتصال شبكة الجوّال. يمكن أن يتضمّن تطبيقك عنصر <restriction> على النحو التالي:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">

  <restriction
    android:key="downloadOnCellular"
    android:title="@string/download_on_cell_title"
    android:restrictionType="bool"
    android:description="@string/download_on_cell_description"
    android:defaultValue="true" />

</restrictions>

يمكنك استخدام سمة android:key لكلّ إعداد لقراءة قيمتها من حِزمة إعدادات مُدارة. لهذا السبب، يجب أن تحتوي كلّ عملية ضبط على سلسلة مفتاح فريدة، ولا يمكن ترجمة السلسلة. ويجب تحديده باستخدام سلسلة حرفية.

ملاحظة: في التطبيق العلني، يجب استخراج android:title و android:description من ملف موارد مترجم ، كما هو موضّح في مقالة الترجمة باستخدام ملفات الموارد.

يحدِّد التطبيق القيود باستخدام الحِزم ضمن bundle_array. على سبيل المثال، يمكن أن يحدِّد تطبيق يتضمّن خيارات اتصال متعددة بشبكة VPN كل إعدادات خادم VPN في bundle، مع تجميع عدة حِزم معًا في صفيف حِزم:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android" >

  <restriction
    android:key="vpn_configuration_list"
    android:restrictionType="bundle_array">
    <restriction
      android:key="vpn_configuration"
      android:restrictionType="bundle">
      <restriction
        android:key="vpn_server"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_username"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_password"
        android:restrictionType="string"/>
    </restriction>
  </restriction>

</restrictions>

يتم إدراج الأنواع المتوافقة للعنصر android:restrictionType في الجدول 1 ويتم توثيقها في المرجع الخاص بالعنصرَين RestrictionsManager و RestrictionEntry.

الجدول 1: أنواع إدخالات القيود واستخدامها

النوع android:restrictionType الاستخدام المعتاد
TYPE_BOOLEAN "bool" قيمة منطقية، صحيح أو خطأ
TYPE_STRING "string" قيمة سلسلة، مثل اسم
TYPE_INTEGER "integer" عدد صحيح بقيمة تتراوح بين MIN_VALUE و MAX_VALUE
TYPE_CHOICE "choice" قيمة سلسلة يتم اختيارها من android:entryValues، ويتم عرضها عادةً كقائمة اختيار فردي.
TYPE_MULTI_SELECT "multi-select" صفيف سلاسل تحتوي على قيم تم اختيارها من android:entryValues استخدِم هذا الخيار لعرض قائمة متعددة الاختيارات يمكن فيها اختيار أكثر من إدخال واحد، مثل اختيار عناوين معيّنة لإضافتها إلى القائمة المسموح بها.
TYPE_NULL "hidden" نوع القيود المخفية استخدِم هذا النوع للمعلومات التي يجب نقلها ولكن يجب عدم عرضها للمستخدم في واجهة المستخدم. تخزِّن قيمة سلسلة واحدة.
TYPE_BUNDLE_ARRAY "bundle_array" استخدِم هذا الإجراء لتخزين صفائف القيود bundles. تتوفّر هذه الميزة في الإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات).

ملاحظة: يمكن للآلة قراءة android:entryValues ولا يمكن ترجمتها. استخدِم android:entries لعرض قيم مفهومة للمستخدمين ويمكن ترجمتها. يجب أن يكون لكل إدخال فهرس مناظر له في android:entryValues.

التحقّق من عمليات الضبط المُدارة

لا يتم إرسال إشعار تلقائي إلى تطبيقك عندما تغيّر التطبيقات الأخرى إعدادات ملفه الشخصي. بدلاً من ذلك، عليك التحقّق من الإعدادات المُدارة عند بدء تشغيل تطبيقك أو استئنافه، والاستماع إلى نية النظام لمعرفة ما إذا كانت الإعدادات تتغيّر أثناء تشغيل تطبيقك.

لمعرفة إعدادات الضبط الحالية، يستخدم تطبيقك عنصر RestrictionsManager. من المفترض أن يبحث تطبيقك عن الإعدادات المُدارة الحالية في الأوقات التالية:

للحصول على عنصر RestrictionsManager، احصل على النشاط الحالي باستخدام getActivity()، ثم استخدِم طريقة Activity.getSystemService() لهذا النشاط:

Kotlin

var myRestrictionsMgr =
        activity?.getSystemService(Context.RESTRICTIONS_SERVICE) as RestrictionsManager

Java

RestrictionsManager myRestrictionsMgr =
    (RestrictionsManager) getActivity()
        .getSystemService(Context.RESTRICTIONS_SERVICE);

بعد الحصول على RestrictionsManager، يمكنك الحصول على إعدادات الضبط الحالية من خلال استدعاء getApplicationRestrictions():

Kotlin

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

Java

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

ملاحظة: للتيسير، يمكنك أيضًا جلب الإعدادات الحالية باستخدام UserManager، من خلال استدعاء UserManager.getApplicationRestrictions(). تعمل هذه الطريقة بالطريقة نفسها تمامًا مثل RestrictionsManager.getApplicationRestrictions().

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

قراءة الإعدادات المُدارة وتطبيقها

تعرض طريقة getApplicationRestrictions() Bundle يحتوي على زوج مفتاح/قيمة لكلّ إعداد تم ضبطه. تكون قيم جميعها من النوع Boolean وint String وString[]. بعد الحصول على عمليات الضبط المُدارة Bundle، يمكنك التحقّق من إعدادات الضبط الحالية باستخدام طرق Bundle العادية لأنواع البيانات هذه، مثل getBoolean() أو getString().

ملاحظة: تحتوي الإعدادات المُدارة Bundle على عنصر واحد لكلّ إعداد تم ضبطه صراحةً من قِبل أحد مقدّمي الإعدادات المُدارة. ومع ذلك، لا يمكنك افتراض أنّ إعدادات ستكون متوفّرة في الحِزمة لمجرد أنّك حدّدت قيمة تلقائية في ملف XML الخاص بالإعدادات المُدارة.

على تطبيقك اتّخاذ الإجراء المناسب استنادًا إلى إعدادات الضبط المُدار الحالية. على سبيل المثال، إذا كان تطبيقك يتضمّن إعدادًا يحدّد ما إذا كان بإمكانه تنزيل البيانات عبر اتصال شبكة الجوّال، وتبيّن لك أنّ الإعداد مضبوط على false، عليك إيقاف تنزيل البيانات إلا عندما يكون الجهاز متصلاً بشبكة Wi-Fi، كما هو موضّح في مثال الرمز البرمجي التالي:

Kotlin

val appCanUseCellular: Boolean =
        if (appRestrictions.containsKey("downloadOnCellular")) {
            appRestrictions.getBoolean("downloadOnCellular")
        } else {
            // cellularDefault is a boolean using the restriction's default value
            cellularDefault
        }

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

Java

boolean appCanUseCellular;

if (appRestrictions.containsKey("downloadOnCellular")) {
    appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular");
} else {
    // cellularDefault is a boolean using the restriction's default value
    appCanUseCellular = cellularDefault;
}

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

لتطبيق قيود مُدمجة متعددة، اقرأ إدخال القيود bundle_array كمجموعة من كائنات Parcelable وحوِّلها إلى Bundle. في هذا المثال، يتم تحليل بيانات إعدادات كل شبكة VPN واستخدامها لإنشاء قائمة بخيارات الاتصال بالخادم:

Kotlin

// VpnConfig is a sample class used store config data, not defined
val vpnConfigs = mutableListOf<VpnConfig>()

val parcelables: Array<out Parcelable>? =
        appRestrictions.getParcelableArray("vpn_configuration_list")

if (parcelables?.isNotEmpty() == true) {
    // iterate parcelables and cast as bundle
    parcelables.map { it as Bundle }.forEach { vpnConfigBundle ->
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(VpnConfig()
                .setServer(vpnConfigBundle.getString("vpn_server"))
                .setUsername(vpnConfigBundle.getString("vpn_username"))
                .setPassword(vpnConfigBundle.getString("vpn_password")))
    }
}

if (vpnConfigs.isNotEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

Java

// VpnConfig is a sample class used store config data, not defined
List<VpnConfig> vpnConfigs = new ArrayList<>();

Parcelable[] parcelables =
    appRestrictions.getParcelableArray("vpn_configuration_list");

if (parcelables != null && parcelables.length > 0) {
    // iterate parcelables and cast as bundle
    for (int i = 0; i < parcelables.length; i++) {
        Bundle vpnConfigBundle = (Bundle) parcelables[i];
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(new VpnConfig()
            .setServer(vpnConfigBundle.getString("vpn_server"))
            .setUsername(vpnConfigBundle.getString("vpn_username"))
            .setPassword(vpnConfigBundle.getString("vpn_password")));
    }
}

if (!vpnConfigs.isEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

الاستماع إلى التغييرات في الإعدادات المُدارة

عند تغيير الإعدادات المُدارة للتطبيق، يُطلق النظام ACTION_APPLICATION_RESTRICTIONS_CHANGED. يجب أن يستمع تطبيقك إلى هذا الإجراء حتى تتمكّن من تغيير سلوك التطبيق عند تغيير إعدادات الضبط.

ملاحظة: لا يتم إرسال النية ACTION_APPLICATION_RESTRICTIONS_CHANGED إلا إلى المستمعين المسجّلين ديناميكيًا، وليس إلى المستمعين المُعلَن عنهم في بيان التطبيق.

يوضّح الرمز التالي كيفية تسجيل مستقبل بث ديناميكيًا لهذا القصد:

Kotlin

val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED)

val restrictionsReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

        // Get the current configuration bundle
        val appRestrictions = myRestrictionsMgr.applicationRestrictions

        // Check current configuration settings, change your app's UI and
        // functionality as necessary.
    }
}

registerReceiver(restrictionsReceiver, restrictionsFilter)

Java

IntentFilter restrictionsFilter =
    new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
  @Override public void onReceive(Context context, Intent intent) {

    // Get the current configuration bundle
    Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

    // Check current configuration settings, change your app's UI and
    // functionality as necessary.
  }
};

registerReceiver(restrictionsReceiver, restrictionsFilter);

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

إرسال ملاحظات عن الإعدادات المُدارة إلى خدمات إدارة الخدمات الجوّالة (EMM)

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

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

عيّنات تعليمات برمجية إضافية

يوضّح نموذج ManagedConfigurations استخدام واجهات برمجة التطبيقات التي تتناولها هذه الصفحة.

إضافة التطبيقات إلى القائمة المسموح بها أو القائمة المحظورة في الملف الشخصي

قد تعرب متاجر التطبيقات التابعة لجهات خارجية عن اهتمامها باستخدام "الإعدادات المُدارة" للحصول على طريقة موثوقة لتطبيق قائمة تطبيقات محظورة أو قائمة تطبيقات مسموح بها على كلٍّ من الملف الشخصي وميزة consumer المساحة الخاصة، وهي مساحة شخصية إضافية للمستخدمين للحفاظ على التطبيقات الحسّاسة. إذا كنت تطوّر متجر تطبيقات لاستخدامه في المؤسسات وأردت استخدام هذه الميزة، يُرجى إرسال هذا النموذج للتعبير عن اهتمامك واختيار الاهتمام بإضافة متجر تطبيقات تابع لجهة خارجية إلى القائمة المسموح بها ك سبب الردّ في النموذج.