راه‌اندازی پیکربندی‌های مدیریت‌شده

اگر درحال توسعه برنامه‌هایی برای بازار سازمانی هستید، ممکن است لازم باشد الزامات خاصی را که توسط خط‌مشی‌های سازمان تعیین شده است برآورده کنید. پیکربندی‌های مدیریت‌شده، که قبلاً با نام محدودیت‌های برنامه شناخته می‌شد، به سرپرست فناوری اطلاعات سازمان اجازه می‌دهد تنظیمات برنامه‌ها را از راه دور مشخص کند. این قابلیت به‌ویژه برای برنامه‌های تأییدشده توسط سازمان که در نمایه کاری مستقر شده‌اند مفید است.

برای مثال، ممکن است سازمانی الزام کند که برنامه‌های تأییدشده به سرپرست فناوری اطلاعات اجازه دهند:

  • مجاز یا مسدود کردن نشانی‌های وب برای مرورگر وب
  • پیکربندی اینکه آیا برنامه‌ای مجاز است محتوا را ازطریق شبکه تلفن همراه همگام‌سازی کند یا فقط ازطریق Wi-Fi
  • پیکربندی تنظیمات ایمیل برنامه

این راهنما نحوه پیاده‌سازی تنظیمات پیکربندی مدیریت‌شده را در برنامه‌تان نشان می‌دهد. برای مشاهده برنامه‌های نمونه با پیکربندی مدیریت‌شده، ManagedConfigurations را ببینید. اگر توسعه‌دهنده مدیریت پویایی سازمانی (EMM) هستید، به راهنمای Android Management API مراجعه کنید.

توجه: به دلایل تاریخی، این تنظیمات پیکربندی به‌عنوان محدودیت‌ها شناخته می‌شوند و با فایل‌ها و کلاس‌هایی که از این اصطلاح استفاده می‌کنند (مانند RestrictionsManager) پیاده‌سازی می‌شوند. بااین‌حال، این محدودیت‌ها درواقع می‌توانند طیف گسترده‌ای از گزینه‌های پیکربندی را پیاده‌سازی کنند، نه فقط محدودیت‌های مربوط به عملکرد برنامه.

نمای کلی پیکربندی از راه دور

برنامه‌ها گزینه‌های پیکربندی مدیریت‌شده را که سرپرست فناوری اطلاعات می‌تواند از راه دور تنظیم کند تعریف می‌کنند. این‌ها تنظیمات اختیاری هستند که می‌توانند توسط ارائه‌دهنده پیکربندی مدیریت‌شده تغییر کنند. اگر برنامه‌تان در نمایه کاری اجرا می‌شود، سرپرست فناوری اطلاعات می‌تواند پیکربندی مدیریت‌شده برنامه‌تان را تغییر دهد.

ارائه‌دهنده پیکربندی‌های مدیریت‌شده برنامه دیگری است که در همان دستگاه اجرا می‌شود. این برنامه معمولاً توسط سرپرست فناوری اطلاعات کنترل می‌شود. سرپرست فناوری اطلاعات تغییرات پیکربندی را به برنامه ارائه‌دهنده پیکربندی مدیریت‌شده اطلاع می‌دهد. آن برنامه نیز به‌نوبه خود پیکربندی‌های برنامه شما را تغییر می‌دهد.

برای ارائه پیکربندی‌های تحت مدیریت خارجی:

  • پیکربندی‌های مدیریت‌شده را در مانیفست برنامه‌تان اعلام کنید. با این کار، سرپرست فناوری اطلاعات می‌تواند پیکربندی‌های برنامه را ازطریق Google Play API بخواند.
  • هرزمان برنامه ازسر گرفته شد، از شیء RestrictionsManager برای بررسی پیکربندی‌های مدیریت‌شده فعلی استفاده کنید و واسط کاربر و رفتار برنامه‌تان را تغییر دهید تا با آن پیکربندی‌ها مطابقت داشته باشد.
  • به قصد ACTION_APPLICATION_RESTRICTIONS_CHANGED گوش دهید. وقتی این همه‌فرستی را دریافت کردید، RestrictionsManager را بررسی کنید تا ببینید پیکربندی‌های مدیریت‌شده فعلی چیست و هرگونه تغییر لازم را در رفتار برنامه‌تان اعمال کنید.

تعریف پیکربندی‌های مدیریت‌شده

برنامه شما می‌تواند از هر پیکربندی مدیریت‌شده‌ای که می‌خواهید تعریف کنید پشتیبانی کند. پیکربندی‌های مدیریت‌شده برنامه را در فایل پیکربندی‌های مدیریت‌شده اعلام می‌کنید و فایل پیکربندی‌ها را در مانیفست اعلام می‌کنید. ایجاد فایل پیکربندی به برنامه‌های دیگر اجازه می‌دهد پیکربندی‌های مدیریت‌شده‌ای را که برنامه‌تان ارائه می‌دهد بررسی کنند. شرکای EMM می‌توانند بااستفاده از Google Play API، پیکربندی‌های برنامه‌تان را بخوانند.

برای تعریف گزینه‌های پیکربندی از راه دور برنامه‌تان، عنصر زیر را در عنصر <application> مانیفست خود قرار دهید:

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

فایلی با نام app_restrictions.xml در فهرست راهنمای res/xml برنامه‌تان ایجاد کنید. ساختار آن فایل در مرجع RestrictionsManager شرح داده شده است. فایل دارای یک عنصر سطح بالای <restrictions> است که شامل یک عنصر فرزند <restriction> برای هر گزینه پیکربندی است که برنامه دارد.

توجه: نسخه‌های بومی‌سازی‌شده از فایل پیکربندی مدیریت‌شده ایجاد نکنید. برنامه شما فقط می‌تواند یک فایل پیکربندی مدیریت‌شده داشته باشد، بنابراین پیکربندی‌ها برای برنامه شما در همه زبان‌ها یکسان خواهد بود.

در محیط سازمانی، EMM معمولاً از طرح‌واره پیکربندی مدیریت‌شده برای تولید کنسول ازراه‌دور برای سرپرستان فناوری اطلاعات استفاده می‌کند تا سرپرستان بتوانند برنامه شما را ازراه‌دور پیکربندی کنند.

ارائه‌دهنده پیکربندی مدیریت‌شده می‌تواند از برنامه پرس‌وجو کند تا جزئیات پیکربندی‌های دردسترس برنامه، ازجمله نوشتار شرح آن‌ها را پیدا کند. ارائه‌دهنده پیکربندی‌ها و سرپرست فناوری اطلاعات می‌توانند پیکربندی‌های مدیریت‌شده برنامه‌تان را هرزمان بخواهند تغییر دهند، حتی وقتی برنامه درحال اجرا نباشد.

برای مثال، فرض کنید برنامه‌تان را می‌توان از راه دور پیکربندی کرد تا به آن اجازه دهد یا آن را منع کند که داده‌ها را ازطریق اتصال شبکه تلفن همراه بارگیری کند. برنامه شما می‌تواند عنصر <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 در جدول ۱ فهرست شده‌اند و در مرجع RestrictionsManager و RestrictionEntry مستند شده‌اند.

جدول ۱. انواع ورودی محدودیت و کاربرد.

نوع 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 نسخه ۶.۰ (سطح میانای برنامه‌سازی کاربردی ۲۳) دردسترس است.

توجه: android:entryValues ماشین‌خوانا هستند و نمی‌توانند بومی‌سازی شوند. از android:entries برای ارائه مقادیر قابل‌خواندن برای انسان که می‌توانند بومی‌سازی شوند استفاده کنید. هر ورودی باید نمایه متناظری در android:entryValues داشته باشد.

بررسی پیکربندی‌های مدیریت‌شده

وقتی برنامه‌های دیگر تنظیمات پیکربندی برنامه شما را تغییر می‌دهند، برنامه شما به‌طور خودکار مطلع نمی‌شود. درعوض، باید بررسی کنید که پیکربندی‌های مدیریت‌شده هنگام شروع یا ازسرگیری برنامه شما چه هستند و به قصد سیستم گوش دهید تا متوجه شوید که آیا پیکربندی‌ها درحین اجرای برنامه شما تغییر می‌کنند یا نه.

برای اطلاع از تنظیمات پیکربندی فعلی، برنامه‌تان از شیء RestrictionsManager استفاده می‌کند. برنامه شما باید در زمان‌های زیر پیکربندی‌های مدیریت‌شده فعلی را بررسی کند:

برای دریافت شیء RestrictionsManager، فعالیت فعلی را با getActivity() دریافت کنید، سپس متد Activity.getSystemService() آن فعالیت را فراخوانی کنید:

کاتلین

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

جاوا

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

وقتی RestrictionsManager را داشته باشید، می‌توانید تنظیمات پیکربندی فعلی را با فراخوانی روش getApplicationRestrictions() آن دریافت کنید:

کاتلین

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

جاوا

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 داشته باشد، همان‌طور که در کد نمونه زیر نشان داده شده است:

کاتلین

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
}

جاوا

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 تجزیه می‌شود و برای ساختن فهرستی از انتخاب‌های اتصال سرور استفاده می‌شود:

کاتلین

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

جاوا

// 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 فقط به شنوندگانی ارسال می‌شود که به‌صورت پویا ثبت شده‌اند، نه به شنوندگانی که در مانیفست برنامه اعلام شده‌اند.

کد زیر نحوه ثبت پویای گیرنده رویداد ثبت‌شده را برای این هدف نشان می‌دهد:

کاتلین

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)

جاوا

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 مراجعه کنید.

نمونه‌های کد اضافی

نمونه ManagedConfigurations استفاده از میاناهای برنامه‌سازی کاربردی پوشش‌داده‌شده در این صفحه را بیشتر نشان می‌دهد.

مجاز کردن/مسدود کردن برنامه‌ها در نمایه شخصی

فروشگاه‌های برنامه طرف سوم ممکن است برای داشتن روشی مطمئن جهت اعمال فهرست غیرمجازها یا فهرست مجازهای برنامه در نمایه شخصی و ویژگی مصرف‌کننده فضای خصوصی (که فضای شخصی دیگری برای نگهداری برنامه‌های حساس کاربران است) به استفاده از «پیکربندی‌های مدیریت‌شده» ابراز علاقه کنند. اگر فروشگاه برنامه‌ای برای استفاده سازمانی توسعه می‌دهید و می‌خواهید از این ویژگی استفاده کنید، این فرم را ارسال کنید تا علاقه‌مندی خود را ابراز کنید و علاقه‌مند به قرار دادن فروشگاه برنامه شخص ثالث در فهرست مجاز را به‌عنوان دلیل پاسخ در فرم انتخاب کنید.