Cihaz güven sinyallerini almak amacıyla AMAPI SDK'nın kullanımı için bu belgeyi birincil kılavuzunuz olarak kullanmanız gerekir.
AMAPI SDK'sı, uygulamanızın Android Cihaz Politikası (ADP) uygulamasındaki Device Trust sinyallerine erişmesine olanak tanır. Uygulamanız daha sonra bu sinyalleri kullanarak cihazın güven durumunu hesaplayabilir ve seçilen iş mantığını uygulayabilir.
Ön koşullar
- Uygulamanızın, Device Trust sinyallerini okuma yetkisi olmalıdır:
- AMAPI tarafından yönetilen cihazlardaki tamamlayıcı uygulamalar: Politikada
COMPANION_APProlü atanmış uygulamalar, tümüyle yönetilen cihazlarda veya bir iş profilinin içinden (erişim, iş profilinden gelen sinyallerle sınırlı olacak şekilde) izin verilenler listesinde yer almadan cihaz güven sinyallerine erişebilir. Ayrıntılar için Uygulama rollerini yönetme, Politika yapılandırması ve Tamamlayıcı uygulamadan gelen sinyallere erişme başlıklı makaleleri inceleyin. - Diğer tüm uygulamalar ve ortamlar: Kişisel profilden, yönetilmeyen bir cihazdan, özel DPC tarafından yönetilen bir cihazdan veya
COMPANION_APProlü olmadan cihaz güven sinyallerine erişmek için uygulamanızın izin verilenler listesinde olması gerekir. Nasıl başvuracağınızla ilgili bilgi edinmek için cihaz güven sinyalleri erişimi sayfasına gidin.
- AMAPI tarafından yönetilen cihazlardaki tamamlayıcı uygulamalar: Politikada
- Android Enterprise, Play Integrity API paketini istemci uygulamanıza entegre etmenizi ve cihaz güven sinyallerini okuyup bunlara güvenmeden önce sonucu incelemenizi önerir. Play Integrity API kontrollerinde başarısız olan cihazlara ve güvenilirlik durumu belirlemek için kullanılan cihazdan alınan sinyallere güvenilmemelidir. Daha fazla bilgi için Play Integrity belgelerini inceleyebilirsiniz.
Uygulamanızda AMAPI SDK'sı ile entegrasyon
Cihaz güven sinyallerine erişmek için uygulamanızın AMAPI SDK ile entegre edilmesi gerekir. Bu kitaplık ve uygulamanıza nasıl ekleyeceğiniz hakkında daha fazla bilgiyi AMAPI SDK entegrasyon kılavuzunda bulabilirsiniz.
Gerekli izinleri ekleme
Android Enterprise API'nin Device Trust özelliğinden döndürülen bazı sinyaller, uygulamanın bu bilgilere erişmek için gereken izni beyan etmesini gerektirir. Bu izinler şunlardır:
| Sinyal | Gerekli izin |
|---|---|
| Ağ Durumu | ACCESS_NETWORK_STATE |
| Ekran kilidi karmaşıklığı | REQUEST_PASSWORD_COMPLEXITY |
Bu izinler uygulamanın AndroidManifest.xml dosyasında yer almıyorsa Android Enterprise'dan Device Trust API, ilgili sinyalin meta verilerinde PERMISSION_ISSUE değerini döndürür:
internalDeviceSettings=DeviceSettings{
screenLockComplexity=COMPLEXITY_UNSPECIFIED,
internalScreenLockComplexityMetadata=Metadata{
dataIssues=[
DataIssue{
issueType=PERMISSION_ISSUE,
issueLevel=WARNING,
issueDetails=IssueDetailsCase{none}
}
]
},
Daha fazla bilgi için kullanılabilir cihaz güven sinyalleri listesine bakın.
Device Trust sinyallerine erişme adımları
İzin verilenler listesindeki uygulamalar (kişisel profilde veya yönetilmeyen bir cihazda çalışan uygulamalar dahil), sinyal istemeden önce istemci ortamının güncel olduğunu doğrulamalı ve gerekirse hazırlamalıdır.
İzin verilenler listesindeki uygulamaların Device Trust sinyallerine erişmesi için gereken adımlar şunlardır:

Müşteri ortamını doğrulama
Aşağıdaki kod örneğinde, ADP uygulamasının mevcut durumunu okumak için getEnvironment'nin nasıl kullanılacağı gösterilmektedir. Ortam hazır ve güncelse uygulamanız, cihaz güven sinyallerine erişmek için önbelleğe alınmış bir deviceClient örneği kullanabilir (Cihaz güven sinyallerine erişme bölümüne bakın).
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) } 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.. 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()); }
ADP uygulaması yüklüyse ancak güncel değilse uygulamanız, kullanıcı müdahalesi olmadan ADP uygulamasını sessizce güncellemek için prepareEnvironment yöntemini çağırmalıdır.
ADP uygulaması yüklü değilse uygulamanız prepareEnvironment yöntemini çağırarak kullanıcıdan ADP uygulamasını yüklemesini isteyebilir. İstemci ortamını hazırlama başlıklı makaleyi inceleyin.
İstemci ortamını hazırlama
ADP uygulaması zaten yüklüyse API, kullanıcı müdahalesi olmadan uygulamayı sessizce günceller.
ADP uygulaması yüklü değilse API, kullanıcıdan ADP uygulamasının yüklenmesini kabul etmesini ister.
Kullanıcı tercihini izlemek için bir geri çağırma işlevi kaydedebilirsiniz. Daha fazla bilgi için ADP uygulaması yükleme sırasında kullanıcı etkileşimini izleme başlıklı makaleyi inceleyin.
Kullanıcıyı Android Device Policy'yi yükle kalıcı iletişim kutusuyla şaşırtmamak için prepareEnvironment çağrısının, ilk katılım kullanıcı deneyimi akışı sırasında bir ön plan işleminden yapılmasını öneririz.
Bu bir web akışı olduğundan ve Android bileşeninin kullanıcı arayüzü olmadığından ön plan işleminden çağrı yapmak mümkün değilse oryantasyon kullanıcı deneyimi akışı sırasında gerçekleşmesi şartıyla arka plandan çağrı yapılmasına izin verilir.
Ortam doğru şekilde ayarlandıktan sonra cihaz güven sinyallerine erişmek mümkündür. Device Trust sinyallerine erişme başlıklı makaleyi inceleyin.
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) } 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.. 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()); }
Cihaz güven sinyallerine erişme
DeviceClient kullanım önerisi
deviceClient örneği (veya EnvironmentClient örneği) oluşturmak, Android Cihaz Politikası (ADP) uygulamasıyla bir iletişim kanalı oluşturur. Bu kanal, boştayken otomatik olarak ayrılır. İstemci örnekleri açık bir kapatma yöntemi sunmadığından, birden fazla örnek oluşturup silmek, artık kanalların çöp olarak toplanmasına neden olur.
Performansı optimize etmek ve sahipsiz kanalları önlemek için DeviceClientFactory.create(context.applicationContext) kullanarak uygulama kapsamında tek bir DeviceClient örneği oluşturun ve uygulamanız genelinde yeniden kullanmak üzere önbelleğe alın (ör. uygulama kapsamlı bir singleton olarak veya bağımlılık ekleme kullanarak).
İlgilendiğiniz cihaz güven sinyallerine erişmek için önbelleğe alınmış deviceClient örneğinizi kullanarak Device nesnesini isteyin:
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) }
Java
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, t.toString()); } }, MoreExecutors.directExecutor());
Tamamlayıcı uygulamadan gelen sinyallere erişme
Tümüyle yönetilen cihazlarda veya Android Management API (AMAPI) ile yönetilen bir iş profilinde, COMPANION_APP rolü atanmış bir uygulama, izin verilenler listesine kaydedilmeden cihaz güven sinyallerini okuyabilir.
Bir iş profilinden (şirkete ait veya kişisel bir cihazda) çağrıldığında uygulamanız iş profilinde çalışmalıdır ve erişim, iş profilinden gelen sinyallerle sınırlıdır (örneğin, yönetim durumu, ekran kilidi karmaşıklığı ve yüklü uygulamalar yalnızca iş profilini yansıtır).
1. Politikada COMPANION_APP rolünü atama
applications politika listesinde uygulamanıza roleType: "COMPANION_APP" izni vermek için EMM politikanızı yapılandırın:
- Uygulamanızın manifest dosyasını yapılandırmak ve isteğe bağlı olarak rol atamalarını dinlemek için Uygulama rollerini yönetme başlıklı makaleyi inceleyin.
- Politika yapılandırma söz dizimi için Politika Yapılandırması başlıklı makaleyi inceleyin.
2. Sinyalleri doğrudan DeviceClient ile okuma
DeviceClientFactory.create kullanarak uygulama kapsamında tek bir deviceClient örneği oluşturup önbelleğe alın (DeviceClient kullanım önerisi bölümüne bakın), ardından Device nesnesini doğrudan isteyin:
Kotlin
import android.content.Context import android.util.Log import com.google.android.managementapi.device.DeviceClient import com.google.android.managementapi.device.DeviceClientFactory import com.google.android.managementapi.device.model.GetDeviceRequest // Instantiate once at application scope (for example, using dependency injection) // to reuse a single DeviceClient instance across your app. class DeviceTrustRepository(context: Context) { private val deviceClient: DeviceClient = DeviceClientFactory.create(context.applicationContext) suspend fun readSignalsFromCompanionApp() { runCatching { deviceClient.getDeviceAwait(GetDeviceRequest.getDefaultInstance()) }.onSuccess { device -> Log.d(TAG, "Device signals: $device") }.onFailure { t -> Log.e(TAG, "Failed to read device signals", t) } } companion object { private const val TAG = "DeviceTrustRepository" } }
Java
import android.content.Context; import android.util.Log; 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.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; // Instantiate once at application scope (for example, using dependency injection) // to reuse a single DeviceClient instance across your app. public class DeviceTrustRepository { private static final String TAG = "DeviceTrustRepository"; private final DeviceClient deviceClient; public DeviceTrustRepository(Context context) { this.deviceClient = DeviceClientFactory.create(context.getApplicationContext()); } public void readSignalsFromCompanionApp() { ListenableFuturedeviceFuture = deviceClient.getDevice(GetDeviceRequest.getDefaultInstance()); Futures.addCallback(deviceFuture, new FutureCallback () { @Override public void onSuccess(Device device) { Log.d(TAG, "Device signals: " + device); } @Override public void onFailure(Throwable t) { Log.e(TAG, "Failed to read device signals", t); } }, MoreExecutors.directExecutor()); } }
Hataları işleme
Uygulamanız cihaz güveni isteğinde bulunur ve çağrı başarısız olursa uygulamanız bir istisna alır. Bu istisnalar, aşağıdakiler gibi çeşitli nedenlerden kaynaklanabilir:
SecurityException: Uygulamanızın istekte bulunma yetkisi yoktur (örneğin, uygulamanız gerektiğinde izin verilenler listesine kaydedilmemiştir, AMAPI tarafından yönetilen bir cihazdaCOMPANION_APProlü atanmamıştır veya izin verilenler listesinde olmayan tamamlayıcı bir uygulama olarakprepareEnvironmentçağrılmıştır). Cihaz güven sinyallerine erişim ve Tamamlayıcı uygulamadan sinyallere erişme başlıklı makaleleri inceleyin.AmapiSdkExceptionalt sınıfı: ADP yok veya hazır değil. Bu, geçici bir durumdan kaynaklanabilir ve aramayı yeniden denemeniz gerekir.
Yeniden deneme stratejileri
Geçici bir durumdan kaynaklanan istisnalar için eksponansiyel geri yükleme ile yeniden deneme stratejisi uygulayın. İlk başarısız denemeden sonra, yeniden denemeden önce 5 saniyelik bir başlangıç gecikmesiyle başlayın.
Çıkış koşulu olarak maksimum deneme sayısına sahip bir yeniden deneme stratejisi uygulayın ve her seferinde üstel olarak artan bir gecikme (10 sn, 20 sn vb.) kullanın.
ADP uygulaması yüklenirken kullanıcı etkileşimini izleme
Cihazın prepareEnvironment sırasında ADP uygulamasını yüklemesi gerekiyorsa uygulamanız, getPrepareEnvironmentListener'i geçersiz kılan bildirimleri almak için NotificationReceiverService uygulayarak kullanıcı etkileşimini izleyebilir:
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"); } } }
Bilinen sorunlar
Şu anda bilinen bir sorun yoktur.