В этом руководстве описаны функции управления сетями и телефонией, которые можно реализовать в приложении контроллера правил для устройств (DPC). Документ содержит образцы кода. В качестве источника образцов кода для корпоративных функций Android также можно использовать приложение Test DPC.
Приложение DPC может работать в режиме владельца профиля на личных устройствах или в режиме владельца устройства на полностью управляемых устройствах. В таблице ниже указано, какие функции доступны, когда контроллер политики устройств работает в режиме владельца профиля или владельца устройства.
Доступ к рабочим контактам из разных профилей
EMM-решения могут разрешать доступ к рабочим контактам из личного профиля пользователя, чтобы он мог находить личные и рабочие контакты с помощью локального поиска и удаленного поиска в каталоге. На личных устройствах одна программа набора номера в личном профиле может совершать и принимать как личные, так и рабочие звонки. Кроме того, рабочие контакты хорошо интегрированы в интерфейс системы. Если рабочий профиль зашифрован, его данные недоступны для личного профиля.
Интеграция с системным интерфейсом
Входящие рабочие вызовы обозначаются значком портфеля. В callLog также показывается значок, обозначающий входящие и исходящие рабочие вызовы. Приложения для звонков и контактов в личном профиле могут показывать информацию о звонящем из рабочего профиля, используя удаленный поиск по каталогу. Для этого не требуется синхронизировать контакт с локальным устройством. Мессенджер может выполнять локальный поиск и определять номера.
В документе с описанием совместимости Android (CDD) указаны требования к показу рабочих контактов в номеронабирателе по умолчанию, а также требования к пометке контактов и мессенджеров, чтобы было понятно, что они относятся к рабочему профилю.
Рабочие контакты доступны и их можно найти
Пользователь может просматривать рабочие контакты и звонить им из личного профиля. Они отображаются на экране поиска приложения для звонков. Пользователь может искать рабочие контакты, синхронизированные с устройством, с помощью автозаполнения, а также просматривать их в удаленном каталоге.
Управление рабочими контактами в основном профиле
Разрешение на поиск рабочих контактов контролируется контроллером политики устройств. В режиме владельца профиля контроллер политики управляет видимостью рабочих контактов в личном профиле. Подробнее о том, как создать контроллер правил для устройств…
Поиск рабочих контактов в личном профиле включен по умолчанию.
Чтобы посмотреть, как настроено правило, используйте
DevicePolicyManager.getCrossProfileContactsSearchDisabled().Чтобы включить или отключить поиск рабочих контактов в личном профиле, используйте
DevicePolicyManager.setCrossProfileContactsSearchDisabled().
Обеспечьте безопасное сетевое подключение для рабочего трафика
Контроллер политик устройств, работающий в режиме владельца устройства или профиля, может использовать постоянное подключение к виртуальной частной сети (VPN), чтобы принудительно направлять трафик приложений через указанное VPN-приложение, которое нельзя обойти. Используя постоянное VPN-подключение, контроллер политики устройств может обеспечить передачу сетевого трафика из рабочего профиля или управляемого устройства через VPN-сервис без вмешательства пользователя. Таким образом повышается уровень безопасности сетевого подключения для трафика в рабочем профиле.
О постоянных VPN-подключениях
Маршрутизация VPN управляется автоматически, поэтому пользователь не может обойти VPN-сервис. Если VPN-сервис отключится в режиме блокировки, трафик не попадет в открытый интернет. Для приложений, в которых реализован класс VpnService, постоянная VPN предоставляет фреймворк, позволяющий управлять защищенным VPN-подключением через доверенный сервер и поддерживать его. VPN-сервис автоматически перезапускает подключение при обновлении приложения, независимо от того, используется ли Wi-Fi или мобильная сеть. Если устройство перезагружается, фреймворк перезапускает VPN-подключение.
Подключение к VPN-сервису происходит незаметно для пользователя. Если устройство принадлежит компании, пользователю не нужно подтверждать согласие на использование VPN в режиме постоянного подключения. Настройки VPN-сети пользователя позволяют вручную включить постоянное подключение.
Если для правила DISALLOW_CONFIG_VPN задано значение true, пользователь не сможет настраивать VPN. Включите правило DISALLOW_DEBUGGING_FEATURES, чтобы запретить пользователям отключать постоянную сеть VPN с помощью команды отладки adb.
Чтобы запретить пользователю удалять VPN, вызовите DevicePolicyManager.setUninstallBlocked.
Как настроить VPN-сервис
Организация, которая использует ваше корпоративное решение для Android, настраивает VPN.
- Установите VPN-приложение, в котором реализован класс
VpnService. Чтобы найти активные VPN-сервисы, используйте фильтр интентов, соответствующий действиюVpnService.SERVICE_INTERFACE. - Объявите
VpnServiceв манифесте приложения, защищенном разрешениемBIND_VPN_SERVICE. - Настройте
VpnServiceтак, чтобы он запускался системой. Не настраивайте приложение VPN так, чтобы оно запускалось при загрузке системы и управляло своим жизненным циклом. - Задайте управляемые конфигурации для VPN-приложения (см. пример ниже).
Как включить постоянное VPN-подключение
Контроллер политики устройств может настроить постоянное VPN-подключение через определенное приложение, вызвав метод DevicePolicyManager.setAlwaysOnVpnPackage().
Это подключение предоставляется автоматически и сохраняется после перезагрузки. Если для параметра lockdownEnabled задано значение False, сетевой трафик может быть незащищенным в период между перезагрузкой телефона и VPN-подключением. Это полезно, если вы не хотите, чтобы сетевое подключение прерывалось при сбое VPN, или если VPN не является обязательным.
Как проверить постоянное VPN-подключение
Контроллер политики устройств может считывать название пакета, управляющего постоянным VPN-подключением для текущего пользователя, с помощью метода DevicePolicyManager.getAlwaysOnVpnPackage()..
Если такого пакета нет или VPN-подключение было создано в системном приложении "Настройки", возвращается значение null.
Пример
В приложении TestDPC AlwaysOnVpnFragment.java использует эти API, чтобы включить параметр для постоянного VPN-подключения.
Рассмотрим пример:
- Управляемые конфигурации VPN-сервиса задаются
DevicePolicyManagerс помощью методаsetApplicationRestrictions(). - В управляемых конфигурациях используются произвольные пары "ключ-значение". В нашем примере приложения они применяются для настройки параметров сети VPN (см. раздел Проверка управляемых конфигураций).
- В примере ниже установщик пакетов Android добавляется в черный список, чтобы он не обновлял системные пакеты через VPN. Весь сетевой трафик пользователя в рабочем профиле или на устройстве проходит через это VPN-приложение, за исключением установщика пакетов, обновления которого используют открытый интернет.
- Затем
DevicePolicyManagerвключает постоянное VPN-подключение для пакета VPN с помощьюsetAlwaysOnVpnPackage()и активирует режим блокировки.
Kotlin
// Set VPN's managed configurations val config = Bundle().apply { putString(Extras.VpnApp.ADDRESS, "192.0.2.0") putString(Extras.VpnApp.IDENTITY, "vpn.account1") putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate") putStringArray(Extras.VpnApp.DENYLIST, arrayOf("com.android.packageinstaller")) } val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager val admin = myDeviceAdminReceiver.getComponentName(this) // Name of package to update managed configurations val vpnPackageName = "com.example.vpnservice" // Associate managed configurations with DeviceAdminReceiver dpm.setApplicationRestrictions(admin, vpnPackageName, config) // Enable always-on VPN connection through VPN package try { val lockdownEnabled = true dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled) } catch (ex: Exception) { throw PolicyException() }
Java
// Set VPN's managed configurations final Bundle config = new Bundle(); config.putString(Extras.VpnApp.ADDRESS, "192.0.2.0"); config.putString(Extras.VpnApp.IDENTITY, "vpn.account1"); config.putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate"); config.putStringArray(Extras.VpnApp.DENYLIST, new String[]{"com.android.packageinstaller"}); DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); ComponentName admin = myDeviceAdminReceiver.getComponentName(this); // Name of package to update managed configurations final String vpnPackageName = "com.example.vpnservice"; // Associate managed configurations with DeviceAdminReceiver dpm.setApplicationRestrictions(admin, vpnPackageName, config); // Enable always-on VPN connection through VPN package try { boolean lockdownEnabled = true; dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled)); } catch (Exception ex) { throw new PolicyException(...); }
Как настроить один идентификатор беспроводной сети для нескольких регионов
Контроллер политик устройств (DPC), работающий в режиме владельца устройства или профиля, может связать несколько сертификатов центра сертификации (ЦС) с одной конфигурацией беспроводной сети. При такой конфигурации устройство может подключаться к беспроводным точкам доступа, которые имеют одинаковое название сети или идентификатор беспроводной сети (SSID), но настроены с разными сертификатами ЦС. Это удобно, если беспроводные сети вашей организации расположены в нескольких географических регионах и для каждого региона требуется отдельный центр сертификации. Например, для юридических подписей может потребоваться местный орган власти, которому нужен региональный ЦС.
Примечание. Android поддерживает setCaCertificate с API 18 (Jelly Bean), но системные администраторы должны настраивать сети отдельно для каждого ЦС, чтобы обеспечить бесперебойную аутентификацию устройств в каждой точке доступа независимо от региона.
Укажите сертификаты ЦС для идентификации сервера
Чтобы указать список сертификатов X.509, которые идентифицируют сервер, использующий тот же SSID, включите все нужные ЦС в конфигурацию беспроводной сети с помощью WifiEnterpriseConfig.setCaCertificates().
Сертификат сервера считается действительным, если его ЦС совпадает с одним из указанных сертификатов.
Сертификатам автоматически присваиваются названия по умолчанию, которые используются в конфигурации. WifiManager устанавливает сертификат и автоматически сохраняет конфигурацию, когда сеть включена, и удаляет сертификат, когда конфигурация удалена.
Чтобы получить все сертификаты ЦС, связанные с конфигурацией беспроводной сети, используйте WifiEnterpriseConfig.getCaCertificates(). Будет возвращен список объектов X509Certificate.
Как добавить конфигурацию беспроводной сети с несколькими сертификатами ЦС
- Проверьте идентификационные данные сервера:
- Загрузите сертификаты ЦС X.509.
- Загрузите закрытый ключ и сертификат клиента. Пример того, как прочитать файл сертификата, можно найти в статье Security with HTTPS and SSL (Обеспечение безопасности с помощью HTTPS и SSL).
- Создайте новую сеть
WifiConfiguration, укажите ее SSID и настройте управление ключами. - Настройте экземпляр
WifiEnterpriseConfigна этом устройстве (WifiConfiguration).- Укажите сервер со списком объектов
X509Certificate, используяsetCaCertificates(). - Укажите учетные данные клиента, идентификатор и пароль.
- При установке подключения задайте расширяемый протокол аутентификации (EAP) и метод второго этапа.
- Укажите сервер со списком объектов
- Добавьте сеть с помощью
WifiManager. - Включите сеть. WifiManager автоматически сохраняет конфигурацию во время настройки.
В этом примере показано, как связать шаги:
Kotlin
// Verify the server's identity val caCert0 = getCaCert("cert0.crt") val caCert1 = getCaCert("cert1.crt") val clientKey = getClientKey() val clientCert = getClientCert() // Create Wi-Fi configuration val wifiConfig = WifiConfiguration().apply { SSID = "mynetwork" allowedKeyManagement.set(KeyMgmt.WPA_EAP) allowedKeyManagement.set(KeyMgmt.IEEE8021X) // Set up Wi-Fi enterprise configuration enterpriseConfig.setCaCertificates(arrayOf<X509Certificate>(caCert0, caCert1)) enterpriseConfig.setClientKeyEntry(clientKey, clientCert) enterpriseConfig.setIdentity("myusername") enterpriseConfig.setEapMethod(Eap.TLS) enterpriseConfig.setPhase2Method(Phase2.NONE) } // Add network val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager val netId = wifiManager.addNetwork(wifiConfig) // Enable network if (netId < 0) { // Error creating new network } else { wifiManager.enableNetwork(netId, true) }
Java
// Verify the server's identity X509Certificate caCert0 = getCaCert("cert0.crt"); X509Certificate caCert1 = getCaCert("cert1.crt"); PrivateKey clientKey = getClientKey(); X509Certificate clientCert = getClientCert(); // Create Wi-Fi configuration WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = "mynetwork"; wifiConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP); wifiConfig.allowedKeyManagement.set(KeyMgmt.IEEE8021X); // Set up Wi-Fi enterprise configuration wifiConfig.enterpriseConfig.setCaCertificates(new X509Certificate[] {caCert0, caCert1}); wifiConfig.enterpriseConfig.setClientKeyEntry(clientKey, clientCert); wifiConfig.enterpriseConfig.setIdentity("myusername"); wifiConfig.enterpriseConfig.setEapMethod(Eap.TLS); wifiConfig.enterpriseConfig.setPhase2Method(Phase2.NONE); // Add network WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); int netId = wifiManager.addNetwork(wifiConfig); // Enable network if (netId < 0) { // Error creating new network } else { wifiManager.enableNetwork(netId, true); }
Как указать отдельное приложение для звонков в рабочем профиле
Вы можете добавить в белый список отдельное приложение для звонков, которое будет использоваться в рабочем профиле.
Это может быть как само приложение для набора номера, так и приложение для IP-телефонии, в котором реализован API ConnectionService для серверной части. Это позволяет использовать системный интерфейс для звонков в приложениях VoIP в рабочем профиле, фактически делая рабочий номеронабиратель основной функцией. Входящие вызовы на рабочие аккаунты для звонков отличаются от входящих вызовов на личные аккаунты для звонков.
Пользователь может совершать и принимать звонки с помощью одобренного рабочего приложения для звонков в аккаунте телефона. Все вызовы, сделанные с помощью этого приложения или поступившие на рабочий номер, записываются в CallLog рабочего профиля. В рабочем профиле ведется отдельный список вызовов, и у него есть доступ только к рабочим контактам. Входящие звонки с коммутацией каналов обрабатываются основным приложением для звонков и сохраняются в личном списке вызовов. Если рабочий профиль удален, список вызовов, связанный с ним, также удаляется вместе со всеми данными рабочего профиля.
Сторонние приложения должны использовать ConnectionService
Сторонние приложения для VoIP-телефонии, которым нужно совершать звонки и интегрировать их со встроенным приложением "Телефон", могут использовать API ConnectionService. Это необходимо для любого сервиса VoIP, используемого для рабочих звонков. Звонки в таких приложениях обрабатываются так же, как и обычные вызовы по сотовой связи. Например, они отображаются во встроенном системном номеронабирателе и списке вызовов. Если приложение, реализующее ConnectionService, установлено в рабочем профиле, оно доступно только для номеронабирателя, также установленного в этом рабочем профиле.
После реализации ConnectionService разработчик должен добавить его в файл манифеста приложения и зарегистрировать PhoneAccount с помощью TelecomManager.
Аккаунт для звонков – это отдельный способ совершать и принимать вызовы. Для каждого ConnectionService может быть несколько PhoneAccounts. После регистрации аккаунта пользователь может включить его в настройках приложения для звонков.
Интеграция с системным интерфейсом и уведомлениями
Системный интерфейс обеспечивает пользователям единообразный и интегрированный опыт набора номера для сторонних приложений, которые используют API ConnectionService в качестве серверной части для совершения звонков. Если вы используете приложение в рабочем профиле, при входящих вызовах и в строке состояния будет показываться значок портфеля. Приложение, которое реализует ConnectionService и установлено в рабочем профиле, может использовать системный номеронабиратель или создать отдельный рабочий номеронабиратель. Это может быть одно приложение или несколько.
Приложение для набора номера определяет, является ли звонок рабочим, по флагу android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL.
Если звонок рабочий, на панели набора номера показывается значок портфеля.
Kotlin
// Call placed through a work phone account. getCurrentCall() is defined by the // dialer. val call = getCurrentCall() if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) { // Set briefcase icon }
Java
// Call placed through a work phone account. getCurrentCall() is defined by the // dialer. Call call = getCurrentCall(); if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) { // Set briefcase icon }