Ten dokument powinien być Twoim głównym przewodnikiem po pakiecie AMAPI SDK na potrzeby otrzymywania sygnałów zaufania urządzenia.
Pakiet SDK AMAPI umożliwia aplikacji (którą czasami nazywamy aplikacją „towarzyszącą”) dostęp do sygnałów o zaufaniu do urządzenia z aplikacji ADP (Android Device Policy). Aplikacja może następnie używać tych sygnałów do obliczania stanu zaufania urządzenia i wdrażania wybranej logiki biznesowej.
Wymagania wstępne
- Dostęp do sygnałów zaufania urządzenia jest ograniczony, aby zapobiec nieautoryzowanemu użyciu. Informacje o tym, jak złożyć wniosek, znajdziesz na stronie dostępu do sygnałów zaufania urządzenia.
- Android Enterprise zaleca zintegrowanie pakietu interfejsów Play Integrity z aplikacją klienta i odwoływanie się do wyników przed odczytaniem i używaniem sygnałów zaufania urządzenia. Urządzenia, które nie przechodzą kontroli interfejsu Play Integrity API, nie powinny być uznawane za godne zaufania, podobnie jak sygnały pochodzące z urządzenia używanego do określania zaufania. Aby dowiedzieć się więcej, zapoznaj się z dokumentacją dotyczącą integralności w Google Play.
Integracja pakietu AMAPI SDK z aplikacją
Aby uzyskać dostęp do sygnałów zaufania urządzenia, aplikacja musi zostać zintegrowana z pakietem AMAPI SDK. Więcej informacji o tej bibliotece i sposobie jej dodania do aplikacji znajdziesz w przewodniku po integracji pakietu AMAPI SDK.
Dodawanie wymaganych uprawnień
Niektóre sygnały zwracane przez interfejs API zaufanie urządzenia w Androidzie Enterprise wymagają, aby aplikacja deklarowała te same uprawnienia, które byłyby wymagane do uzyskania dostępu do tych informacji. W szczególności:
Sygnał | Wymagane uprawnienie |
---|---|
Stan sieci | ACCESS_NETWORK_STATE |
Złożoność blokady ekranu | REQUEST_PASSWORD_COMPLEXITY |
Jeśli te uprawnienia nie są uwzględnione w AndroidManifest.xml
aplikacji, zaufanie do urządzenia z Androida Enterprise zwraca wartość PERMISSION_ISSUE
w metadanych powiązanego sygnału:
internalDeviceSettings=DeviceSettings{
screenLockComplexity=COMPLEXITY_UNSPECIFIED,
internalScreenLockComplexityMetadata=Metadata{
dataIssues=[
DataIssue{
issueType=PERMISSION_ISSUE,
issueLevel=WARNING,
issueDetails=IssueDetailsCase{none}
}
]
},
Więcej informacji znajdziesz na liście dostępnych sygnałów zaufania urządzenia.
Jak uzyskać dostęp do sygnałów zaufania urządzenia
Aplikacje, które chcą uzyskać dostęp do sygnałów zaufania urządzenia, muszą zweryfikować, czy środowisko klienta jest aktualne, i w razie potrzeby je zaktualizować.
Aby uzyskać dostęp do sygnałów zaufania do urządzenia:
- Sprawdzanie środowiska klienta
- Przygotowanie środowiska klienta
- Dostęp do sygnałów zaufania urządzenia
Weryfikacja środowiska klienta
Z przykładu kodu poniżej dowiesz się, jak za pomocą funkcji getEnvironment
odczytać bieżący stan aplikacji ADP. Następnie aplikacja może utworzyć obiekt deviceClient
, aby uzyskać dostęp do sygnałów zaufania urządzenia, jeśli środowisko jest gotowe i aktualne (patrz Dostęp do sygnałów zaufania urządzenia).
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()); }
Jeśli aplikacja ADP jest zainstalowana, ale nie jest aktualna, Twoja aplikacja powinna wywołać funkcję prepareEnvironment
, aby dyskretnie zaktualizować aplikację ADP bez udziału użytkownika.
Jeśli aplikacja ADP nie jest zainstalowana, może wywołać funkcję prepareEnvironment
, aby poprosić użytkownika o zainstalowanie aplikacji ADP. Zapoznaj się z sekcją Przygotowanie środowiska klienta.
Przygotowanie środowiska klienta
Jeśli aplikacja ADP jest już zainstalowana, interfejs API zaktualizuje ją bez udziału użytkownika.
Jeśli aplikacja ADP nie jest zainstalowana, interfejs API poprosi użytkownika o zaakceptowanie instalacji aplikacji ADP.
Aby monitorować wybór użytkownika, możesz zarejestrować wywołanie zwrotne. Więcej informacji znajdziesz w artykule Śledzenie interakcji użytkowników podczas instalacji aplikacji ADP.
Zalecamy, aby wywołanie prepareEnvironment
było wykonywane w procesie czołowym podczas procesu wprowadzania użytkownika, aby nie zaskakiwać go oknem modalnym Zainstaluj Android Device Policy.
Jeśli wywołanie z procesu na pierwszym planie jest niemożliwe, ponieważ jest to proces internetowy, a komponent na Androida nie ma interfejsu użytkownika, wywołanie z tła jest dozwolone, ale tylko podczas procesu wdrażania.
Po prawidłowym skonfigurowaniu środowiska można uzyskać dostęp do sygnałów zaufania urządzenia. Zapoznaj się z artykułem Dostęp do sygnałów o zaufaniu do urządzenia.
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()); }
Dostęp do sygnałów zaufania do urządzenia
Aby uzyskać dostęp do interesujących Cię sygnałów zaufania urządzenia, możesz użyć instancji deviceClient
, którą widzisz w poprzednim kroku, aby zażądać obiektu 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()); }
Śledzenie interakcji użytkownika podczas instalowania aplikacji ADP
Jeśli podczas prepareEnvironment
aplikacja musi zainstalować aplikację ADP, może śledzić interakcje użytkownika, wdrażając NotificationReceiverService
, aby otrzymywać powiadomienia, które zastąpią 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"); } } }
Znane problemy
Obecnie nie ma żadnych znanych problemów.