Este documento é seu guia principal para o uso do SDK da AMAPI com o objetivo de receber indicadores de confiança do dispositivo.
O SDK AMAPI permite que seu aplicativo (que às vezes chamamos de app "complementar") acesse indicadores de confiança do dispositivo no app ADP (Política de dispositivos Android). Em seguida, seu app pode usar esses indicadores para calcular o estado de confiança do dispositivo e implementar a lógica de negócios conforme escolhido.
Pré-requisitos
- O acesso aos indicadores de confiança do dispositivo é restrito para evitar o uso não autorizado. Para saber como se inscrever, acesse a página Acesso aos indicadores de confiança do dispositivo.
- O Android Enterprise recomenda integrar o conjunto de APIs Play Integrity ao aplicativo cliente e consultar o resultado antes de ler e confiar nos indicadores de confiança do dispositivo. Não confie em dispositivos que falham nas verificações da API Play Integrity nem em indicadores derivados do dispositivo usado para determinar a postura de confiança. Consulte a documentação da Play Integrity para mais detalhes.
Integrar com o SDK da AMAPI no seu aplicativo
Para acessar os indicadores de confiança do dispositivo, seu aplicativo precisa ser integrado ao SDK da AMAPI. Para mais informações sobre essa biblioteca e como adicioná-la ao seu aplicativo, consulte o guia de integração do SDK da AMAPI.
Adicionar as permissões necessárias
Alguns dos indicadores retornados pela API Device Trust do Android Enterprise exigem que o app declare a mesma permissão que seria necessária para acessar essas informações em primeiro lugar, principalmente:
Indicador | Permissão necessária |
---|---|
Estado da rede | ACCESS_NETWORK_STATE |
Complexidade do bloqueio de tela | REQUEST_PASSWORD_COMPLEXITY |
Se essas permissões não estiverem incluídas no AndroidManifest.xml
do app, a
API Device Trust do Android Enterprise vai retornar PERMISSION_ISSUE
nos
metadados do indicador relacionado:
internalDeviceSettings=DeviceSettings{
screenLockComplexity=COMPLEXITY_UNSPECIFIED,
internalScreenLockComplexityMetadata=Metadata{
dataIssues=[
DataIssue{
issueType=PERMISSION_ISSUE,
issueLevel=WARNING,
issueDetails=IssueDetailsCase{none}
}
]
},
Para mais detalhes, consulte a lista de indicadores de confiança do dispositivo disponíveis.
Etapas para acessar os indicadores de confiança do dispositivo
Os aplicativos que querem acessar os indicadores de confiança do dispositivo precisam verificar se o ambiente do cliente está atualizado e atualizá-lo, se necessário.
Para acessar os indicadores de confiança do dispositivo, siga estas etapas:
- Verificar o ambiente do cliente
- Preparar o ambiente do cliente
- Acessar indicadores de confiança do dispositivo
Verificar o ambiente do cliente
O exemplo de código a seguir mostra como usar getEnvironment
para ler o
estado atual do app ADP. Em seguida, seu aplicativo pode criar um
deviceClient
para acessar os indicadores de confiança do dispositivo se o ambiente estiver pronto
e atualizado. Consulte Acessar indicadores de confiança do dispositivo.
Kotlin
import com.google.android.managementapi.common.model.Role import com.google.android.managementapi.device.DeviceClient import com.google.android.managementapi.device.DeviceClientFactory import com.google.android.managementapi.device.model.GetDeviceRequest import com.google.android.managementapi.environment.EnvironmentClient import com.google.android.managementapi.environment.EnvironmentClientFactory import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.INSTALLED import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.NOT_INSTALLED import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE import com.google.android.managementapi.environment.model.GetEnvironmentRequest import com.google.android.managementapi.environment.model.PrepareEnvironmentRequest try { val context = applicationContext val roles = listOf(Role.builder().setRoleType(Role.RoleType.IDENTITY_PROVIDER).build()) val request = GetEnvironmentRequest.builder().setRoles(roles).build() val environmentClient = EnvironmentClientFactory.create(context) val environmentResponse = environmentClient.getEnvironment(request) if (environmentResponse.hasAndroidDevicePolicyEnvironment()) { val adpEnvironment = environmentResponse.androidDevicePolicyEnvironment if (adpEnvironment.state == READY && adpEnvironment.version == UP_TO_DATE) { // AMAPI Environment State OK, Version OK. Requesting Device signals.. checkDevice(deviceClient = DeviceClientFactory.create(context)) } else if (adpEnvironment.state == INSTALLED) { // prepareEnvironment should be called, calling // prepareEnvironment won't show the UI prepareEnvironment(context, environmentClient) } else if (adpEnvironment.state == NOT_INSTALLED) { // prepareEnvironment should be called, calling // prepareEnvironment will show the UI prepareEnvironment(context, environmentClient) } } } catch (e: Exception) { Log.e(TAG, "Exception", e) }
Java
import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.INSTALLED; import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.NOT_INSTALLED; import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.State.READY; import static com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment.Version.UP_TO_DATE; import com.google.android.managementapi.common.model.Role; import com.google.android.managementapi.device.DeviceClient; import com.google.android.managementapi.device.DeviceClientFactory; import com.google.android.managementapi.device.model.Device; import com.google.android.managementapi.device.model.GetDeviceRequest; import com.google.android.managementapi.environment.EnvironmentClient; import com.google.android.managementapi.environment.EnvironmentClientFactory; import com.google.android.managementapi.environment.model.Environment; import com.google.android.managementapi.environment.model.Environment.AndroidDevicePolicyEnvironment; import com.google.android.managementapi.environment.model.GetEnvironmentRequest; import com.google.android.managementapi.environment.model.PrepareEnvironmentRequest; import com.google.android.managementapi.environment.model.PrepareEnvironmentResponse; try { Context context = getApplicationContext(); ImmutableListroles = new ImmutableList.Builder () .add(Role.builder() .setRoleType(Role.RoleType.IDENTITY_PROVIDER) .build()) .build(); EnvironmentClient environmentClient = EnvironmentClientFactory.create(context); GetEnvironmentRequest request = GetEnvironmentRequest.builder() .setRoles(roles) .build(); ListenableFuture getEnvironmentFuture = environmentClient.getEnvironmentAsync(request); Futures.addCallback(getEnvironmentFuture, new FutureCallback<>() { @Override public void onSuccess(Environment environment) { AndroidDevicePolicyEnvironment adpEnvironment = environment.getAndroidDevicePolicyEnvironment(); AndroidDevicePolicyEnvironment.State state = adpEnvironment.getState(); AndroidDevicePolicyEnvironment.Version version = adpEnvironment.getVersion(); if (state == READY && version == UP_TO_DATE) { // AMAPI Environment State OK, Version OK. Requesting Device signals.. DeviceClient deviceClient = DeviceClientFactory.create(context); checkDevice(deviceClient); } else if (state == INSTALLED) { // prepareEnvironment should be called, calling // prepareEnvironment won't show the UI prepareEnvironment(context, environmentClient); } else if (state == NOT_INSTALLED) { // prepareEnvironment should be called, calling // prepareEnvironment will show the UI prepareEnvironment(context, environmentClient); } } @Override public void onFailure(Throwable t) { Log.d(TAG, t.toString()); } }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.d(TAG, e.toString()); }
Se o app ADP estiver instalado, mas não atualizado, seu aplicativo vai chamar
prepareEnvironment
para atualizar silenciosamente o app ADP sem intervenção do usuário.
Se o app ADP não estiver instalado, seu aplicativo poderá chamar prepareEnvironment
para pedir que o usuário instale o app ADP. Consulte
Preparar o ambiente do cliente.
Preparar o ambiente do cliente
Se o app ADP já estiver instalado, a API o atualizará silenciosamente sem intervenção do usuário.
Se o app ADP não estiver instalado, a API vai pedir que o usuário aceite a instalação.
É possível registrar um callback para monitorar a escolha do usuário. Consulte Rastrear a interação do usuário durante a instalação do app ADP para mais detalhes.
Recomendamos que a chamada prepareEnvironment
seja feita de um processo em primeiro plano durante o fluxo de UX de integração para evitar surpreender o usuário com a caixa de diálogo modal Instalar o Android Device Policy.
Se não for possível fazer chamadas de um processo em primeiro plano, porque este é um fluxo da Web
e o componente Android não tem interface, é permitido fazer chamadas em segundo plano com
a exigência de que isso aconteça durante o fluxo de UX de integração.
Depois que o ambiente estiver configurado corretamente, será possível acessar os indicadores de confiança do dispositivo. Consulte Acessar indicadores de confiança do dispositivo.
Kotlin
try { val myNotificationReceiverService = ComponentName( context, MyNotificationReceiverService::class.java ) val roles = listOf(Role.builder().setRoleType(Role.RoleType.IDENTITY_PROVIDER).build()) val request = PrepareEnvironmentRequest.builder().setRoles(roles).build() val response = environmentClient.prepareEnvironment(request, myNotificationReceiverService) val environment = response.environment val adpEnvironment = environment.androidDevicePolicyEnvironment val state = adpEnvironment.state val version = adpEnvironment.version if (state == READY && version == UP_TO_DATE) { // Environment is prepared, access device posture signals using // DeviceClient. checkDevice(deviceClient = DeviceClientFactory.create(context)) } else { // The prepareEnvironment call failed to prepare Log.w( TAG, "AMAPI environment was not ready: " + state + " - " + version ) } } catch (e: java.lang.Exception) { Log.d(TAG, e.toString()) }
Java
try { ComponentName myNotificationReceiverService = new ComponentName( context, MyNotificationReceiverService.class ); ImmutableListroles = new ImmutableList.Builder () .add(Role.builder() .setRoleType(Role.RoleType.IDENTITY_PROVIDER) .build()) .build(); PrepareEnvironmentRequest request = PrepareEnvironmentRequest.builder() .setRoles(roles) .build(); ListenableFuture environmentFuture = environmentClient.prepareEnvironmentAsync( request, myNotificationReceiverService ); Futures.addCallback(environmentFuture, new FutureCallback<>() { @Override public void onSuccess(PrepareEnvironmentResponse response) { Environment environment = response.getEnvironment(); AndroidDevicePolicyEnvironment adpEnvironment = environment.getAndroidDevicePolicyEnvironment(); AndroidDevicePolicyEnvironment.State state = adpEnvironment.getState(); AndroidDevicePolicyEnvironment.Version version = adpEnvironment.getVersion(); if (state == READY && version == UP_TO_DATE) { // AMAPI Environment State OK, Version OK. Requesting Device signals.. DeviceClient deviceClient = DeviceClientFactory.create(context); checkDevice(deviceClient); } else { // The prepareEnvironment call failed to prepare Log.w( TAG, "AMAPI environment was not ready: " + adpEnvironment.getState() + " - " + adpEnvironment.getVersion() ); } } @Override public void onFailure(@NonNull Throwable t) { // Handle the error Log.d(TAG, "AMAPI response did not contain an ADP environment"); } }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.d(TAG, e.toString()); }
Acessar indicadores de confiança do dispositivo
Para acessar os indicadores de confiança do dispositivo que você quer, use a instância deviceClient
vista na etapa anterior para solicitar o objeto Device
.
Kotlin
try { kotlin.runCatching { deviceClient.getDeviceAwait(GetDeviceRequest.getDefaultInstance()) }.onFailure { t -> Log.d(TAG, t.toString()) }.onSuccess { device -> // Access device posture signals available in device val deviceString = device.toString() Log.d(TAG, deviceString) } } catch (e: java.lang.Exception) { Log.d(TAG, e.toString()) }
Java
try { ListenableFuturedeviceFuture = deviceClient.getDevice(GetDeviceRequest.getDefaultInstance()); Futures.addCallback(deviceFuture, new FutureCallback () { @Override public void onSuccess(Device device) { // Access device posture signals available in device String deviceString = device.toString(); Log.d(TAG, deviceString); } @Override public void onFailure(Throwable t) { Log.d(TAG, Log.d(TAG, t.toString()); } }, MoreExecutors.directExecutor()); } catch (Exception e) { Log.d(TAG, e.toString()); }
Acompanhar a interação do usuário durante a instalação do app ADP
Se o dispositivo precisar instalar o app ADP durante a prepareEnvironment
, seu
aplicativo poderá rastrear a interação do usuário implementando um
NotificationReceiverService
para receber notificações substituindo
getPrepareEnvironmentListener
:
Kotlin
import android.util.Log import com.google.android.managementapi.environment.EnvironmentListener import com.google.android.managementapi.environment.model.EnvironmentEvent.EventCase.Kind.ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED import com.google.android.managementapi.environment.model.EnvironmentEvent import com.google.android.managementapi.notification.NotificationReceiverService class MyNotificationReceiverService : NotificationReceiverService() { override fun getPrepareEnvironmentListener(): EnvironmentListener { return MyEnvironmentListener() } } class MyEnvironmentListener : EnvironmentListener { override fun onEnvironmentEvent( event: EnvironmentEvent ) { if (event.event.kind == ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED) { Log.d(TAG, "User provided install consent") } else { Log.d(TAG, "User rejected install consent") } } companion object { private val TAG: String = MyEnvironmentListener::class.java.simpleName } }
Java
import static com.google.android.managementapi.environment.model.EnvironmentEvent.EventCase.Kind.ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED; import android.util.Log; import androidx.annotation.NonNull; import com.google.android.managementapi.environment.EnvironmentListener; import com.google.android.managementapi.environment.model.EnvironmentEvent; import com.google.android.managementapi.notification.NotificationReceiverService; class MyNotificationReceiverService extends NotificationReceiverService { @NonNull @Override protected EnvironmentListener getPrepareEnvironmentListener() { return new MyEnvironmentListener(); } } class MyEnvironmentListener implements EnvironmentListener { final private String TAG = MyEnvironmentListener.class.getSimpleName(); @Override public void onEnvironmentEvent(EnvironmentEvent event) { if (event.getEvent().getKind() == ANDROID_DEVICE_POLICY_INSTALL_CONSENT_ACCEPTED) { Log.d(TAG, "User provided install consent"); } else { Log.d(TAG, "User rejected install consent"); } } }
Problemas conhecidos
Não há problemas conhecidos no momento.