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 oRestrictionsManager
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
.
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:
- Quando o aplicativo é iniciado ou retomado, na
Método
onResume()
- Quando o app é notificado sobre uma mudança de configuração, conforme descrito em Detectar configurações gerenciadas Mudanças
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.