Este documento debe ser tu guía principal para usar el SDK de AMAPI con el fin de recibir indicadores de confianza del dispositivo.
El SDK de AMAPI permite que tu aplicación (a la que, en ocasiones, nos referimos como una app "compañera") acceda a los indicadores de confianza del dispositivo desde la app de la ADP (política de dispositivos Android). Luego, tu app puede usar estos indicadores para calcular el estado de confianza del dispositivo y aplicar la lógica empresarial según se elija.
Requisitos previos
- El acceso a los indicadores de confianza del dispositivo está restringido para evitar el uso no autorizado. Para obtener información sobre cómo postularte, ve a la página acceso a los indicadores de confianza del dispositivo.
- Android Enterprise recomienda integrar el paquete de APIs de Play Integrity en tu aplicación cliente y consultar el resultado antes de leer y depender de los indicadores de confianza del dispositivo. No se debe confiar en los dispositivos que no aprueban las verificaciones de la API de Play Integrity ni en los indicadores derivados del dispositivo que se usan para tomar decisiones sobre la postura de confianza. Para obtener más detalles, consulta la documentación de Play Integrity.
Realiza la integración con el SDK de AMAPI en tu aplicación
Para acceder a los indicadores de confianza del dispositivo, tu aplicación debe integrarse con el SDK de AMAPI. Puedes encontrar más información sobre esta biblioteca y cómo agregarla a tu aplicación en la guía de integración del SDK de AMAPI.
Agrega los permisos necesarios
Algunos de los indicadores que se muestran en la API de Device Trust de Android Enterprise requieren que la app declare el mismo permiso que se necesitaría para acceder a esta información en primer lugar, en particular:
Indicador | Permiso necesario |
---|---|
Estado de la red | ACCESS_NETWORK_STATE |
Complejidad del bloqueo de pantalla | REQUEST_PASSWORD_COMPLEXITY |
Si estos permisos no se incluyen en el AndroidManifest.xml
de la app, la API de Device Trust de Android Enterprise mostrará PERMISSION_ISSUE
en los metadatos del indicador relacionado:
internalDeviceSettings=DeviceSettings{
screenLockComplexity=COMPLEXITY_UNSPECIFIED,
internalScreenLockComplexityMetadata=Metadata{
dataIssues=[
DataIssue{
issueType=PERMISSION_ISSUE,
issueLevel=WARNING,
issueDetails=IssueDetailsCase{none}
}
]
},
Para obtener más detalles, consulta la lista de los indicadores de confianza del dispositivo disponibles.
Pasos para acceder a los indicadores de confianza del dispositivo
Las aplicaciones que quieran acceder a los indicadores de confianza del dispositivo deben verificar que el entorno del cliente esté actualizado y, si es necesario, actualizarlo.
Los pasos para acceder a los indicadores de confianza del dispositivo son los siguientes:
- Verifica el entorno del cliente
- Prepara el entorno del cliente
- Cómo acceder a los indicadores de confianza del dispositivo
Verifica el entorno del cliente
En el siguiente ejemplo de código, se muestra cómo usar getEnvironment
para leer el estado actual de la app de ADP. Luego, tu aplicación puede crear un deviceClient
para acceder a los indicadores de confianza del dispositivo si el entorno está listo y actualizado (consulta Cómo acceder a los indicadores de confianza del 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()); }
Si la app de ADP está instalada, pero no está actualizada, tu aplicación debe llamar a prepareEnvironment
para actualizarla de forma silenciosa sin intervención del usuario.
Si la app de ADP no está instalada, tu aplicación puede llamar a prepareEnvironment
para solicitarle al usuario que instale la app de ADP. Consulta Cómo preparar el entorno del cliente.
Prepara el entorno del cliente
Si la app de ADP ya está instalada, la API la actualizará de forma silenciosa sin intervención del usuario.
Si la app de ADP no está instalada, la API le pedirá al usuario que acepte la instalacin de la app de ADP.
Es posible registrar una devolución de llamada para supervisar la elección del usuario. Consulta Cómo hacer un seguimiento de la interacción del usuario durante la instalación de la app de ADP para obtener más detalles.
Te recomendamos que la llamada a prepareEnvironment
se realice desde un proceso en primer plano, durante el flujo de UX de integración, para evitar sorprender al usuario con el diálogo modal Install Android Device Policy.
Si no es posible realizar una llamada desde un proceso en primer plano, porque se trata de un flujo web y el componente de Android no tiene IU, se permite realizar una llamada desde segundo plano con el requisito de que esto suceda durante el flujo de UX de integración.
Una vez que el entorno esté configurado correctamente, es posible acceder a los indicadores de confianza del dispositivo. Consulta Cómo acceder a los indicadores de confianza del 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()); }
Accede a los indicadores de confianza del dispositivo
Para acceder a los indicadores de confianza del dispositivo que te interesan, puedes usar la instancia de deviceClient
que se vio en el paso anterior para solicitar el 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()); }
Realiza un seguimiento de la interacción del usuario durante la instalación de la app de ADP
Si el dispositivo necesita instalar la app de ADP durante prepareEnvironment
, tu aplicación puede hacer un seguimiento de la interacción del usuario que registra un servicio para recibir notificaciones:
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 conocidos
Por el momento, no hay problemas conocidos.