Если вы разрабатываете приложения для корпоративного рынка, вам может потребоваться соблюдать определенные требования, установленные правилами организации. Управляемые конфигурации, ранее известные как ограничения для приложений, позволяют системному администратору организации удаленно задавать настройки приложений. Эта возможность особенно полезна для одобренных организацией приложений, развернутых в рабочем профиле.
Например, в организации может быть установлено требование, чтобы одобренные приложения позволяли системному администратору:
- Как разрешить или заблокировать URL в браузере
- Укажите, разрешено ли приложению синхронизировать контент через мобильную сеть или только через 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 перечислены в таблице 1 и описаны в справочных материалах по RestrictionsManager и RestrictionEntry.
Таблица 1. Типы и использование записей об ограничениях.
| Тип | android:restrictionType | Типичное использование |
|---|---|---|
TYPE_BOOLEAN
|
"bool" |
Логическое значение: true или false. |
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 (уровень API 23).
|
Примечание. Значения android:entryValues предназначены для компьютеров и не могут быть локализованы. Используйте android:entries, чтобы показывать человекочитаемые значения, которые можно локализовать.
Каждая запись должна иметь соответствующий индекс в android:entryValues.
Проверьте управляемые конфигурации
Ваше приложение не получает автоматических уведомлений, когда другие приложения изменяют его настройки. Вместо этого вам нужно проверять управляемые конфигурации при запуске или возобновлении работы приложения, а также отслеживать системные намерения, чтобы узнавать об изменении конфигураций во время работы приложения.
Чтобы узнать текущие настройки конфигурации, приложение использует объект RestrictionsManager. Приложение должно проверять текущие управляемые конфигурации в следующие моменты:
- При запуске или возобновлении работы приложения в методе
onResume(). - Когда приложение получает уведомление об изменении конфигурации, как описано в разделе Отслеживание изменений управляемой конфигурации.
Чтобы получить объект 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 демонстрирует использование API, описанных на этой странице.
Добавление приложений в белый или черный список в личном профиле.
Сторонние магазины приложений могут использовать управляемые конфигурации, чтобы применять белый или черный список приложений как к личному профилю, так и к частному пространству – дополнительному личному пространству, где пользователи могут хранить приложения с конфиденциальными данными. Если вы разрабатываете магазин приложений для корпоративного использования и хотите использовать эту функцию, заполните эту форму, выбрав в качестве причины обращения вариант Interest in 3P app store allowlisting (Интерес к белому списку сторонних магазинов приложений).