Gerenciar funções de aplicativos

O recurso de papéis de aplicativo permite que um admin de TI conceda permissões especiais a um aplicativo gerenciado em um dispositivo Android. Ao atribuir um papel específico, um app pode ser isento de restrições de energia e segundo plano, suspensão, hibernação (no Android 14 ou mais recente) e ter controles do usuário (ou seja, inclui ações do usuário, como forçar a interrupção e limpar os dados do app) desativados (no Android 11 ou mais recente), permitindo que ele execute a função essencial sem interrupção. Além disso, o app pode ser notificado sobre os papéis atribuídos, o que permite que ele seja inicializado sem intervenção do usuário.

Para uma lista de papéis de aplicativo disponíveis e os privilégios especiais concedidos a cada papel, consulte RoleType.

Pré-requisitos

O dispositivo é gerenciado por um EMM baseado na AMAPI (não há suporte para EMMs que usam um DPC personalizado).

Preparar o app para usar o recurso

A integração com o SDK da AMAPI só é necessária se o app quiser ser notificado sobre os papéis atribuídos, o que permite que ele seja inicializado automaticamente (ou seja, inicialização automática sem interação do usuário).

Integrar com o SDK da AMAPI no app

Você pode encontrar mais informações sobre o SDK da AMAPI e como adicioná-lo ao app em o guia de integração do SDK da AMAPI.

Adicionar os metadados necessários ao manifesto do app

O Android Device Policy (ADP) precisa saber o ComponentName da classe que implementa NotificationReceiverService para notificar seu app sobre os papéis atribuídos. Você precisa marcar seu serviço em AndroidManifest.xml adequadamente para que ele possa ser descoberto automaticamente pelo ADP.

  • Seu app precisa ter exatamente um serviço enabled e ter meta-data com android:name igual a com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES
  • Esse serviço precisa ter android:exported definido como true
  • O android:value do meta-data precisa ser definido como uma string vazia
<service
 android:name=".MyNotificationReceiverService"
 android:exported="true">
    <meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES" android:value="" />
</service>

Se você estiver testando o papel COMPANION_APP, também adicione o seguinte meta-data ao serviço para que o Android Device Policy possa enviar atualizações de status de comando local ao app:

<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_COMMAND_STATUS" android:value="" />

Criar um serviço que estenda NotificationReceiverService (ou atualizar o existente)

Crie ou atualize o NotificationReceiverService e implemente um AppRolesListener para detectar os papéis atribuídos ao app. Somente getAppRolesListener() é necessário para detectar os papéis atribuídos ao app. Se o app receber um papel COMPANION_APP, você também precisará implementar 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"
  }
}

Seu app poderá ser notificado várias vezes se os papéis mudarem várias vezes. Se todos os papéis forem removidos, seu app ainda será notificado com uma lista vazia de papéis. Essa notificação vai tirar o app do estado interrompido e, junto com as isenções concedidas, o app poderá ser inicializado sem interação do usuário. Graças à notificação e às isenções de papéis do app, ele pode detectar ACTION_BOOT_COMPLETED transmissões. Se o app depende das configurações gerenciadas para ser inicializado, consulte Configurar configurações gerenciadas para saber como ler e detectar mudanças.

Provisionar o dispositivo com políticas de papéis de app

Os desenvolvedores de apps podem testar a atribuição de papéis de app ao aplicativo usando um EMM ou seguindo o guia de início rápido da API Android Management. O notebook do Colab da AMAPI permite inscrever uma empresa, criar uma política e provisionar um dispositivo.

Definir a política do app com papéis de app

Configure um policy com os papéis de app que o app deve ter usando os ApplicationPolicy.roles.

O exemplo a seguir mostra como configurar o papel para apps MTD:

{
  "applications": [

    {
      "packageName": "com.example.mtd",
      "installType": "FORCE_INSTALLED",
      "roles": [
        { "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
      ]
    }
  ]
}

Antes de atribuir os papéis especificados na política, o sistema vai verificar se a impressão digital do certificado da chave de assinatura do app no dispositivo corresponde à da Google Play Store. Se a impressão digital for diferente, os papéis não serão atribuídos ao app, e NonComplianceReason.APP_SIGNING_CERT_MISMATCH a não conformidade será informada ao EMM.

{
  "applications": [

    {
      "packageName": "com.example.mtd",
      "installType": "FORCE_INSTALLED",
      "signingKeyCerts": [
         { "signingKeyCertFingerprintSha256": "base64-encoded-sha256" }
       ],
      "roles": [
        { "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
      ]
    }
  ]
}

Se o app tiver uma configuração gerenciada, o administrador de TI poderá configurar uma configuração inicial configuração para as restrictions relevantes na política do aplicativo:

{
  "applications": [

    {
      "packageName": "com.example.mtd",
      "installType": "FORCE_INSTALLED",
      "roles": [
        { "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
      ],
      "managedConfiguration": {
        "<key>": "<value>"
      }
    }
  ]
}

Verificar o status de isenção da bateria

Os apps com o papel de defesa contra ameaças móveis (MTD, na sigla em inglês) são automaticamente isentos das restrições padrão de energia em segundo plano. No entanto, essa isenção é implementada pelo bucket de App em espera, e não pela lista de permissões de energia do sistema.

Para verificar se a isenção do app está ativa:

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