Definir configurações gerenciadas

Se você desenvolver aplicativos para o mercado corporativo, pode ser necessário para atender a requisitos específicos definidos pelas políticas de uma organização. As configurações gerenciadas, antes conhecidas como restrições de aplicativos, permitem que o administrador de TI da organização especifique remotamente as configurações para apps. Esse recurso é útil principalmente para aplicativos implantados em um perfil de trabalho.

Por exemplo, uma organização pode exigir que os apps aprovados permitam o administrador de TI para:

  • Permitir ou bloquear URLs em um navegador da Web
  • Configurar se um app tem permissão para sincronizar conteúdo por rede celular ou apenas por Wi-Fi
  • Definir as configurações de e-mail do app

Este guia mostra como implementar definições de configuração gerenciadas no seu app. Para ver os apps de exemplo com uma configuração gerenciada, consulte ManagedConfigurations. Se você é um desenvolvedor de gerenciamento de mobilidade empresarial (EMM), consulte o guia da API Android Management.

Observação: por motivos históricos, essas definições de configuração são conhecidas como restrictions,e são implementados com arquivos e classes que usam esse termo (como RestrictionsManager). No entanto, podem implementar uma grande variedade de opções de configuração, e não apenas restrições à funcionalidade do app.

Visão geral da Configuração remota

Os apps definem as opções de configuração gerenciada que podem ser remotas definido por um administrador de TI. Essas são configurações arbitrárias que podem ser por um provedor de configuração gerenciado. Caso seu app esteja sendo executado em um perfil de trabalho, o administrador de TI pode alterar a configuração gerenciada do app.

O provedor de configurações gerenciadas é outro app executado no mesmo dispositivo. Normalmente, este app é controlado pelo administrador de TI. A O administrador de TI informa as mudanças de configuração aos do provedor de configuração. Esse app, por sua vez, muda as configurações no seu app.

Para fornecer configurações gerenciadas externamente:

  • Declarar as configurações gerenciadas no manifesto do app. Fazer o que permite que o administrador de TI leia usando as APIs do Google Play.
  • Sempre que o app for retomado, use o objeto RestrictionsManager para verificar o estado atual configurações gerenciadas e mudar a interface e o comportamento do app para estão em conformidade com essas configurações.
  • Ouça o ACTION_APPLICATION_RESTRICTIONS_CHANGED. Quando você receber isso transmissão, verifique o RestrictionsManager para ver o que quais são as configurações gerenciadas atuais e fazer as alterações necessárias nas comportamento do app.

Definir configurações gerenciadas

Seu app oferece suporte a qualquer configuração gerenciada que você quiser definir. Você declara o as configurações gerenciadas do app em um arquivo de configurações gerenciadas e declarar o arquivo de configurações no manifesto. Criar um arquivo de configurações permite e outros apps para analisar as configurações gerenciadas fornecidas. Parceiros de EMM podem ler as configurações do app usando as APIs do Google Play.

Para definir as opções de configuração remota do app, coloque o seguinte elemento na linha de comando Elemento <application>:

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

Crie um arquivo chamado app_restrictions.xml no arquivo res/xml. A estrutura desse arquivo é descrita em a referência para RestrictionsManager. O arquivo tem único elemento <restrictions> de nível superior, que contém um elemento filho <restriction> para cada configuração que o app tem.

Observação:não crie versões localizadas do de configuração gerenciada. Seu app só pode ter um um único arquivo de configurações gerenciadas. Assim, as configurações serão consistentes para seu app em todas as localidades.

Em um ambiente empresarial, um EMM geralmente usa a plataforma de configuração do Terraform para gerar um console remoto para administradores. Assim, eles podem configurar remotamente seus para o aplicativo.

O provedor de configuração gerenciada pode consultar o app para encontrar detalhes nas configurações disponíveis do app, incluindo a descrição delas em textos. O provedor de configurações e o administrador de TI podem alterar as configurações configurações gerenciadas a qualquer momento, mesmo quando o app não está em execução.

Por exemplo, suponha que seu app possa ser configurado remotamente para permitir ou proibir para fazer o download de dados por uma conexão celular. Seu app pode ter um <restriction> como este:

<?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>

Use o atributo android:key de cada configuração para ler o valor dele em um pacote de configuração gerenciado. Por isso, cada configuração precisa ter uma string de chave exclusiva, e a string não pode ser localizado. Ele precisa ser especificado com um literal de string.

Observação:em um app de produção, android:title e android:description precisa ser extraído de um recurso localizado. , conforme descrito em Localizar com recursos.

Um app define restrições usando pacotes em um bundle_array. Por exemplo, um app com várias opções de conexão VPN poderia definir cada servidor VPN em um bundle, com várias pacotes agrupados em uma matriz de pacotes:

<?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>

Os tipos compatíveis com o elemento android:restrictionType estão listadas na Tabela 1 e documentadas em a referência para RestrictionsManager e RestrictionEntry.

Tabela 1. Tipos de entrada de restrição e uso.

Tipo Tipo de restrição de Android Uso normal
TYPE_BOOLEAN "bool" Um valor booleano, verdadeiro ou falso.
TYPE_STRING "string" Um valor de string, como um nome.
TYPE_INTEGER "integer" Um número inteiro com um valor de MIN_VALUE a MAX_VALUE.
TYPE_CHOICE "choice" Um valor de string selecionado em android:entryValues; normalmente apresentado como uma lista de seleção única.
TYPE_MULTI_SELECT "multi-select" Uma matriz de strings com valores selecionados em android:entryValues. Use este recurso para apresentar uma lista de seleção múltipla em que mais de um entrada pode ser selecionada, por exemplo, para escolher títulos específicos para colocar na lista de permissões.
TYPE_NULL "hidden" Tipo de restrição oculto. Use esse tipo para informações que precisa ser transferido, mas não deve ser apresentado a o usuário na interface. Armazena um único valor de string.
TYPE_BUNDLE_ARRAY "bundle_array" Use para armazenar matrizes de restrição bundles: Disponível no Android 6.0 (nível 23 da API).

Observação: android:entryValues são legíveis por máquina e não podem ser localizada. Use android:entries para apresentar valores legíveis que podem ser localizados. Cada entrada precisa ter um índice correspondente em android:entryValues.

Verificar as configurações gerenciadas

Seu app não é notificado automaticamente quando outros apps alteram definições de configuração. Em vez disso, é preciso verificar o que os de configuração são quando seu app é iniciado ou retomado e detecta um intenção do sistema para descobrir se as configurações mudam enquanto está em execução.

Para descobrir as definições de configuração atuais, seu app usa uma RestrictionsManager. Seu app precisa verifique as configurações gerenciadas atuais nos seguintes horários:

Para conseguir um objeto RestrictionsManager, acesse o atividade com getActivity(), então chame o método Activity.getSystemService() dessa atividade:

Kotlin

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

Java

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

Quando tiver um RestrictionsManager, será possível acessar as definições atuais chamando Método getApplicationRestrictions():

Kotlin

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

Java

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

Observação:para facilitar, você também pode buscar o valor com um UserManager, chamando UserManager.getApplicationRestrictions(). Esse método se comporta exatamente igual a RestrictionsManager.getApplicationRestrictions().

O método getApplicationRestrictions() requer leitura do armazenamento de dados. Portanto, isso deve ser feito com moderação. Não chame esse método sempre que precisar saber a configuração atual. Em vez disso, você deve chamá-lo uma vez quando o app é iniciado ou retomado e armazena em cache o pacote de configurações gerenciadas buscado. Depois, ouça para que a intent ACTION_APPLICATION_RESTRICTIONS_CHANGED descubra se a configuração mudar enquanto o app está ativo, conforme descrito em Escutar mudanças de configuração gerenciadas.

Como ler e aplicar configurações gerenciadas

O método getApplicationRestrictions() retorna um Bundle. contendo um par de chave-valor para cada configuração definida. A todos os valores são do tipo Boolean, int, String e String[]. Assim que tiver configurações gerenciadas Bundle, é possível verificar com os métodos Bundle padrão para esses tipos de dados, como getBoolean() ou getString().

Observação:as configurações gerenciadas Bundle contém um item para cada configuração que foi definida explicitamente por um provedor de configurações gerenciadas. No entanto, não presuma que um configuração estará presente no pacote só porque você definiu uma no arquivo XML de configurações gerenciadas.

Cabe ao seu aplicativo tomar as medidas apropriadas com base no atual configurações gerenciadas. Por exemplo, se o app tiver um que especifica se é possível fazer o download de dados uma conexão celular e descobrir que a configuração está definida como false, seria necessário desativar o download de dados, exceto quando o dispositivo tem uma conexão Wi-Fi, conforme mostrado no código de exemplo a seguir:

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
}

Para aplicar várias restrições aninhadas, leia a bundle_array entrada de restrição como uma coleção de objetos Parcelable e transmitido como um Bundle. Neste exemplo, a configuração de cada VPN os dados são analisados e usados para criar uma lista de opções de conexão do servidor:

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
}

Detectar mudanças de configuração gerenciada

Sempre que as configurações gerenciadas de um app são alteradas, o sistema dispara o ACTION_APPLICATION_RESTRICTIONS_CHANGED. Seu app precisa ouvir essa intent para que você possa alterar o comportamento do app quando as definições de configuração mudar.

Observação:a intent ACTION_APPLICATION_RESTRICTIONS_CHANGED é enviada apenas aos listeners. que são registrados dinamicamente, não para listeners que foram declarados no manifesto do app.

O código a seguir mostra como registrar dinamicamente um broadcast receiver para esta intent:

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);

Observação:normalmente, o app não precisa ser notificado. sobre mudanças de configuração quando ela é pausada. Em vez disso, cancele o registro seu broadcast receiver quando o app estiver pausado. Quando o app é retomado, você verifique as configurações gerenciadas atuais (conforme discutido Verifique as configurações gerenciadas) e registre-se seu broadcast receiver para garantir que você receba notificações sobre alterações de configuração que acontecem enquanto o app está ativo.

Enviar feedback de configuração gerenciada para EMMs

Após aplicar as mudanças de configuração gerenciada ao app, recomendamos notificar os EMMs sobre o status da mudança. O Android tem suporte a um recurso chamado estados de app inseridos, que você pode usar para enviar feedback sempre que o app tentar aplicar mudanças de configuração gerenciada. Isso o feedback pode servir como confirmação de que seu app definiu configurações gerenciadas ou pode incluir uma mensagem de erro se o app não aplicar as mudanças especificadas.

Os provedores de EMM podem recuperar e exibir esse feedback nos próprios consoles para a equipe de TI visualizar. Consulte Enviar feedback do app para EMMs para mais informações informações sobre o assunto, incluindo um guia detalhado sobre como adicionar suporte a feedback no app.

Outros exemplos de código

A configuração ManagedConfigurations exemplo demonstra com mais detalhes o uso das APIs abordadas nesta página.