Dieses Dokument sollte Ihr primärer Leitfaden für die Verwendung des AMAPI SDK zum Empfangen von Gerätevertrauenssignalen sein.
Mit dem AMAPI SDK kann Ihre Anwendung (die wir manchmal auch als „Companion“-App bezeichnen) auf Gerätezustandssignale der ADP-App (Android Device Policy) zugreifen. Ihre App kann diese Signale dann verwenden, um den Vertrauensstatus des Geräts zu berechnen und die ausgewählte Geschäftslogik auszuführen.
Vorbereitung
- Der Zugriff auf die Device-Trust-Signale ist eingeschränkt, um eine unbefugte Nutzung zu verhindern. Informationen zur Bewerbung finden Sie auf der Seite Zugriff auf Device-Trust-Signale.
- Android Enterprise empfiehlt, die Play Integrity-APIs in Ihre Clientanwendung zu integrieren und das Ergebnis zu berücksichtigen, bevor Sie die Gerätevertrauenssignale lesen und sich darauf verlassen. Geräte, die die Prüfungen der Play Integrity API nicht bestehen, sollten nicht als vertrauenswürdig eingestuft werden. Das gilt auch für alle Signale, die vom Gerät abgeleitet werden und zur Bestimmung des Vertrauensstatus verwendet werden. Weitere Informationen finden Sie in der Dokumentation zur Play Integrity API.
AMAPI SDK in Ihre Anwendung einbinden
Um auf die Signale für das Gerätevertrauen zuzugreifen, muss Ihre Anwendung in das AMAPI SDK eingebunden werden. Weitere Informationen zu dieser Bibliothek und dazu, wie Sie sie Ihrer Anwendung hinzufügen, finden Sie im Integrationsleitfaden für das AMAPI SDK.
Erforderliche Berechtigungen hinzufügen
Für einige der Signale, die von der Device Trust from Android Enterprise API zurückgegeben werden, muss die App dieselbe Berechtigung deklarieren, die erforderlich wäre, um auf diese Informationen zuzugreifen, insbesondere:
Signal | Erforderliche Berechtigung |
---|---|
Netzwerkstatus | ACCESS_NETWORK_STATE |
Komplexität der Displaysperre | REQUEST_PASSWORD_COMPLEXITY |
Wenn diese Berechtigungen nicht im AndroidManifest.xml
der App enthalten sind, gibt die Device Trust from Android Enterprise API PERMISSION_ISSUE
in den Metadaten des zugehörigen Signals zurück:
internalDeviceSettings=DeviceSettings{
screenLockComplexity=COMPLEXITY_UNSPECIFIED,
internalScreenLockComplexityMetadata=Metadata{
dataIssues=[
DataIssue{
issueType=PERMISSION_ISSUE,
issueLevel=WARNING,
issueDetails=IssueDetailsCase{none}
}
]
},
Weitere Informationen finden Sie in der Liste der verfügbaren Device Trust-Signale.
Schritte für den Zugriff auf die Device-Trust-Signale
Anwendungen, die auf die Device-Trust-Signale zugreifen möchten, müssen überprüfen, ob die Clientumgebung auf dem neuesten Stand ist, und sie gegebenenfalls aktualisieren.
So greifen Sie auf die Device-Trust-Signale zu:
Clientumgebung überprüfen
Das folgende Codebeispiel zeigt, wie Sie getEnvironment
verwenden, um den aktuellen Status der ADP-App zu lesen. Ihre Anwendung kann dann ein deviceClient
erstellen, um auf die Device-Trust-Signale zuzugreifen, wenn die Umgebung bereit und aktuell ist (siehe Auf Device-Trust-Signale zugreifen).
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()); }
Wenn die ADP-App installiert, aber nicht auf dem neuesten Stand ist, sollte Ihre Anwendung prepareEnvironment
aufrufen, um die ADP-App im Hintergrund ohne Nutzereingriff zu aktualisieren.
Wenn die ADP-App nicht installiert ist, kann Ihre Anwendung prepareEnvironment
aufrufen, um den Nutzer aufzufordern, die ADP-App zu installieren. Weitere Informationen finden Sie unter Clientumgebung vorbereiten.
Clientumgebung vorbereiten
Wenn die ADP-App bereits installiert ist, wird sie von der API automatisch aktualisiert, ohne dass der Nutzer eingreifen muss.
Wenn die ADP-App nicht installiert ist, werden Nutzer von der API aufgefordert, die Installation der ADP-App zu akzeptieren.
Es ist möglich, einen Callback zu registrieren, um die Auswahl des Nutzers zu überwachen. Weitere Informationen finden Sie unter Nutzerinteraktion während der Installation der ADP-App erfassen.
Wir empfehlen, den prepareEnvironment
-Aufruf während des Onboarding-UX-Ablaufs über einen Vordergrundprozess auszuführen, um zu vermeiden, dass der Nutzer vom Modal-Dialogfeld Android Device Policy installieren überrascht wird.
Wenn ein Aufruf über einen Vordergrundprozess nicht möglich ist, weil es sich um einen Web-Ablauf handelt und die Android-Komponente keine Benutzeroberfläche hat, ist ein Aufruf im Hintergrund zulässig. Dies muss jedoch während des Onboarding-UX-Ablaufs erfolgen.
Sobald die Umgebung richtig eingerichtet ist, können Sie auf die Device-Trust-Signale zugreifen. Weitere Informationen finden Sie unter Auf Device-Trust-Signale zugreifen.
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()); }
Auf Device-Trust-Signale zugreifen
Um auf die Device-Trust-Signale zuzugreifen, die Sie interessieren, können Sie die im vorherigen Schritt gezeigte deviceClient
-Instanz verwenden, um das Device
-Objekt anzufordern.
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()); }
Nutzerinteraktionen während der Installation von ADP-Apps erfassen
Wenn auf dem Gerät die ADP-App während der prepareEnvironment
installiert werden muss, kann Ihre Anwendung die Nutzerinteraktion mithilfe von NotificationReceiverService
verfolgen, um Benachrichtigungen zu erhalten, die getPrepareEnvironmentListener
überschreiben:
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"); } } }
Bekannte Probleme
Derzeit sind keine Probleme bekannt.