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

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

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

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

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

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

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

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

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

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

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

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

يمكن أن يوفّر تطبيقك أي ضبط مُدار تريد تحديده. يجب أن تعلن عن عمليات الضبط المُدارة للتطبيق في ملف عمليات ضبط مُدارة، وتوضّح ملف الإعدادات في البيان. ويسمح إنشاء ملف ضبط للتطبيقات الأخرى بفحص عمليات الضبط المُدارة التي يوفّرها تطبيقك. يمكن لشركاء إدارة الخدمات الجوّالة للمؤسسات (EMM) الاطّلاع على إعدادات تطبيقك باستخدام واجهات برمجة تطبيقات 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. أنواع إدخالات القيود واستخدامها

Type 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. تتوفّر هذه الميزة في Android 6.0 (المستوى 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) للحصول على مزيد من المعلومات حول هذا الموضوع، بما في ذلك دليل تفصيلي حول كيفية إضافة دعم التعليقات إلى تطبيقك.

نماذج رموز إضافية

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