Функция ролей приложений позволяет ИТ-администратору предоставлять особые привилегии управляемому приложению на устройстве под управлением Android. Назначая определенную роль, приложение может быть освобождено от ограничений по энергопотреблению и фоновым процессам, приостановлено, переведено в спящий режим (на Android 14+) и иметь отключенные пользовательские элементы управления (например, действия пользователя, такие как принудительная остановка и очистка данных приложения) (на Android 11+), что позволяет ему выполнять свои критически важные функции без прерывания. Кроме того, приложение может получать уведомления о назначенных ему ролях, что позволяет ему запускаться самостоятельно без вмешательства пользователя.
Список доступных ролей приложения и предоставленных каждой роли особых привилегий см. в RoleType .
Предварительные требования
Управление устройством осуществляется с помощью EMM на основе AMAPI (EMM, использующие собственный DPC, не поддерживаются).
Подготовьте ваше приложение к использованию этой функции.
Интеграция с AMAPI SDK необходима только в том случае, если приложение хочет получать уведомления о назначенных ему ролях, что позволяет ему автоматически запускаться (то есть автоматически запускаться без участия пользователя).
Интегрируйте AMAPI SDK в ваше приложение.
Более подробную информацию об AMAPI SDK и о том, как добавить его в ваше приложение, вы найдете в руководстве по интеграции AMAPI SDK .
Добавьте необходимые метаданные в манифест приложения.
Для того чтобы ваше приложение могло получать уведомления о назначенных ему ролях, Android Device Policy (ADP) необходимо знать ComponentName вашего класса, реализующего NotificationReceiverService . Необходимо соответствующим образом пометить ваш сервис в файле AndroidManifest.xml , чтобы ADP мог автоматически его обнаружить.
- В вашем приложении должна быть
enabledровно одна служба,meta-dataкоторой имеют значениеandroid:nameравноеcom.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES. - Для этой службы необходимо установить параметр
android:exportedвtrue - Параметр
android:valueвmeta-dataдолжен быть установлен в пустую строку.
<service
android:name=".MyNotificationReceiverService"
android:exported="true">
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES" android:value="" />
</service>
Если вы тестируете роль COMPANION_APP , вам также следует добавить следующие meta-data в вашу службу, чтобы Android Device Policy мог отправлять локальные обновления статуса команд вашему приложению:
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_COMMAND_STATUS" android:value="" />
Создайте службу, наследующую класс NotificationReceiverService (или обновите существующую).
Создайте или обновите существующий NotificationReceiverService и реализуйте интерфейс AppRolesListener для прослушивания ролей, назначенных вашему приложению. Для прослушивания ролей, назначенных вашему приложению, требуется только getAppRolesListener() . Если вашему приложению назначена роль COMPANION_APP вам также следует реализовать getCommandListener() :
import android.util.Log
import com.google.android.managementapi.approles.AppRolesListener
import com.google.android.managementapi.approles.model.AppRolesSetRequest
import com.google.android.managementapi.approles.model.AppRolesSetResponse
import com.google.android.managementapi.commands.CommandListener
import com.google.android.managementapi.commands.model.Command
import com.google.android.managementapi.notification.NotificationReceiverService
class MyNotificationReceiverService : NotificationReceiverService() {
// If your app wants to listen for roles assigned
override fun getAppRolesListener(): AppRolesListener =
object : AppRolesListener {
override fun onAppRolesSet(request: AppRolesSetRequest): AppRolesSetResponse {
val roleTypes = request.roles.map { role -> role.roleType }
Log.i(TAG, "onAppRolesSet: $roleTypes")
return AppRolesSetResponse.getDefaultInstance()
}
}
// If your app wants to listen for local command status updates
// Only relevant for COMPANION_APP role
override fun getCommandListener(): CommandListener {
return object : CommandListener {
override fun onCommandStatusChanged(command: Command) {
Log.i(TAG, "onCommandStatusChanged")
}
}
}
private companion object {
const val TAG = "MyNotificationReceiverService"
}
}
Ваше приложение может получать уведомления несколько раз, если его роли изменяются неоднократно. Если все роли удалены, ваше приложение все равно получит уведомление с пустым списком ролей. Это уведомление выведет ваше приложение из остановленного состояния, и вместе с предоставленными для него исключениями оно сможет загрузиться самостоятельно без какого-либо взаимодействия с пользователем. Благодаря уведомлениям о ролях приложения и исключениям, ваше приложение может прослушивать широковещательные сообщения ACTION_BOOT_COMPLETED . Если ваше приложение зависит от управляемых конфигураций для загрузки, см. раздел «Настройка управляемых конфигураций», чтобы узнать, как читать и прослушивать изменения.
Настройте устройство с помощью политик ролей приложений.
Разработчики приложений могут протестировать назначение ролей своему приложению, используя EMM или следуя инструкциям в кратком руководстве по Android Management API . Блокнот AMAPI Colab позволяет зарегистрировать предприятие, создать политику и настроить устройство.
Настройте политику для своего приложения с помощью ролей приложения.
Создайте policy с указанием ролей, которые должны быть у вашего приложения, используя файл ApplicationPolicy.roles .
В следующем примере показано, как настроить роль для приложений MTD:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
Перед назначением ролей в соответствии с политикой система проверит, совпадает ли отпечаток сертификата ключа подписи приложения на устройстве с отпечатком из Play Store. Если отпечаток отличается, роли приложению не будут назначены, и в EMM будет отправлено сообщение о несоответствии NonComplianceReason.APP_SIGNING_CERT_MISMATCH .
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"signingKeyCerts": [
{ "signingKeyCertFingerprintSha256": "base64-encoded-sha256" }
],
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
Если в вашем приложении используется управляемая конфигурация, ИТ-администратор может настроить начальную конфигурацию соответствующих restriction в политике приложения:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
],
"managedConfiguration": {
"<key>": "<value>"
}
}
]
}
Проверьте статус освобождения от требований по батареям.
Приложения с ролью Mobile Threat Defense (MTD) автоматически освобождаются от стандартных ограничений энергопотребления в фоновом режиме. Однако это исключение реализуется с помощью App Standby Bucket, а не системного списка разрешенного энергопотребления.
Чтобы проверить, активировано ли исключение для приложения:
import android.app.usage.UsageStatsManager
import android.content.Context
// UsageStatsManager.STANDBY_BUCKET_EXEMPTED is annotated as a @SystemApi. We can redefine it for clarity.
// Define this at the top level of your file, or inside a companion object
private const val STANDBY_BUCKET_EXEMPTED = 5
private fun isAppExemptedFromAppStandbyBucket(): Boolean =
(getSystemService(Context.USAGE_STATS_SERVICE) as? UsageStatsManager)
?.appStandbyBucket == STANDBY_BUCKET_EXEMPTED