این سند باید راهنمای اصلی شما برای استفاده از AMAPI SDK به منظور دریافت سیگنالهای اعتماد دستگاه باشد.
کیت توسعه نرمافزار AMAPI به برنامه شما (که گاهی اوقات ممکن است به عنوان یک برنامه "همراه" از آن یاد کنیم) این امکان را میدهد که به سیگنالهای اعتماد دستگاه از برنامه ADP (سیاست دستگاه اندروید) دسترسی پیدا کند. سپس برنامه شما میتواند از این سیگنالها برای محاسبه وضعیت اعتماد دستگاه و اجرای منطق تجاری انتخاب شده استفاده کند.
پیشنیازها
- دسترسی به سیگنالهای اعتماد دستگاه برای جلوگیری از استفاده غیرمجاز محدود شده است. برای کسب اطلاعات در مورد نحوه درخواست، به صفحه دسترسی به سیگنالهای اعتماد دستگاه مراجعه کنید.
- اندروید انترپرایز توصیه میکند که مجموعه APIهای Play Integrity را در برنامه کلاینت خود ادغام کنید و قبل از خواندن و تکیه بر سیگنالهای اعتماد دستگاه، به نتیجه مراجعه کنید. دستگاههایی که در بررسیهای API Play Integrity ناموفق هستند، نباید مورد اعتماد قرار گیرند، و همچنین هیچ سیگنالی که از دستگاه برای تعیین وضعیت اعتماد گرفته میشود، نباید مورد استفاده قرار گیرد. برای جزئیات بیشتر میتوانید به مستندات Play Integrity مراجعه کنید.
ادغام با AMAPI SDK در برنامه شما
برای دسترسی به سیگنالهای اعتماد دستگاه، برنامه شما باید با AMAPI SDK ادغام شود. میتوانید اطلاعات بیشتر در مورد این کتابخانه و نحوه افزودن آن به برنامه خود را در راهنمای ادغام AMAPI SDK بیابید.
مجوزهای مورد نیاز را اضافه کنید
تعدادی از سیگنالهای برگشتی از Device Trust from Android Enterprise API مستلزم آن است که برنامه همان مجوزی را که برای دسترسی به این اطلاعات در وهله اول لازم است، اعلام کند، به ویژه:
| سیگنال | مجوز لازم |
|---|---|
| وضعیت شبکه | ACCESS_NETWORK_STATE |
| پیچیدگی قفل صفحه | REQUEST_PASSWORD_COMPLEXITY |
اگر این مجوزها در AndroidManifest.xml برنامه گنجانده نشده باشند، Device Trust از Android Enterprise API مقدار PERMISSION_ISSUE در متادیتای سیگنال مربوطه برمیگرداند:
internalDeviceSettings=DeviceSettings{
screenLockComplexity=COMPLEXITY_UNSPECIFIED,
internalScreenLockComplexityMetadata=Metadata{
dataIssues=[
DataIssue{
issueType=PERMISSION_ISSUE,
issueLevel=WARNING,
issueDetails=IssueDetailsCase{none}
}
]
},
برای جزئیات بیشتر، به فهرست سیگنالهای اعتماد دستگاه موجود مراجعه کنید.
مراحل دسترسی به سیگنالهای اعتماد دستگاه
برنامههایی که میخواهند به سیگنالهای اعتماد دستگاه دسترسی پیدا کنند، موظفند بهروزرسانی محیط کلاینت را تأیید کرده و در صورت لزوم آن را بهروزرسانی کنند.
مراحل دسترسی به سیگنالهای اعتماد دستگاه عبارتند از:

محیط کلاینت را بررسی کنید
مثال کد زیر نحوه استفاده از getEnvironment را برای خواندن وضعیت فعلی برنامه ADP نشان میدهد. سپس برنامه شما میتواند یک deviceClient ایجاد کند تا در صورت آماده و بهروز بودن محیط، به سیگنالهای اعتماد دستگاه دسترسی پیدا کند (به بخش دسترسی به سیگنالهای اعتماد دستگاه مراجعه کنید).
کاتلین
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) }
جاوا
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()); }
اگر برنامه ADP نصب شده باشد اما بهروزرسانی نشده باشد، برنامه شما باید تابع prepareEnvironment فراخوانی کند تا برنامه ADP را بدون دخالت کاربر و بهطور بیسروصدا بهروزرسانی کند.
اگر برنامه ADP نصب نشده باشد، برنامه شما میتواند تابع prepareEnvironment فراخوانی کند تا از کاربر بخواهد برنامه ADP را نصب کند. به بخش Prepare the client environment مراجعه کنید.
آماده سازی محیط مشتری
اگر برنامه ADP از قبل نصب شده باشد، API بدون دخالت کاربر و به صورت بیصدا آن را بهروزرسانی میکند.
اگر برنامه ADP نصب نشده باشد، API از کاربر میخواهد که نصب برنامه ADP را بپذیرد.

میتوان یک فراخوانی مجدد برای نظارت بر انتخاب کاربر ثبت کرد. برای جزئیات بیشتر به بخش «ردیابی تعامل کاربر در طول نصب برنامه ADP» مراجعه کنید.
توصیه میکنیم فراخوانی prepareEnvironment از یک فرآیند پیشزمینه، در طول جریان UX آنبوردینگ انجام شود تا از غافلگیر شدن کاربر با پنجره محاورهای نصب سیاست دستگاه اندروید جلوگیری شود. اگر فراخوانی از یک فرآیند پیشزمینه امکانپذیر نیست، زیرا این یک جریان وب است و کامپوننت اندروید رابط کاربری ندارد، فراخوانی از پسزمینه با این شرط مجاز است که این اتفاق در طول جریان UX آنبوردینگ رخ دهد.
پس از تنظیم صحیح محیط، میتوان به سیگنالهای اعتماد دستگاه دسترسی پیدا کرد. به بخش «دسترسی به سیگنالهای اعتماد دستگاه» مراجعه کنید.
کاتلین
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()) }
جاوا
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()); }
دسترسی به سیگنالهای اعتماد دستگاه
برای دسترسی به سیگنالهای اعتماد دستگاه مورد نظرتان، میتوانید از نمونه deviceClient که در مرحله قبل مشاهده کردید، برای درخواست شیء Device استفاده کنید.
کاتلین
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()) }
جاوا
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()); }
مدیریت خطاها
اگر برنامه شما درخواست اعتماد دستگاه را ارسال کند و فراخوانی ناموفق باشد، برنامه شما یک استثنا دریافت میکند. این استثنائات میتوانند به دلایل مختلفی مانند موارد زیر رخ دهند:
-
SecurityException- برنامه شما برای دسترسی به سیگنالهای اعتماد دستگاه ثبت نشده است. به بخش دسترسی به سیگنالهای اعتماد دستگاه مراجعه کنید. - یک زیرکلاس از
AmapiSdkException- ADP موجود نیست یا آماده نیست. این میتواند ناشی از یک وضعیت گذرا باشد و شما باید فراخوانی را دوباره امتحان کنید.
استراتژیهای تلاش مجدد
برای استثنائات ناشی از شرایط گذرا، یک استراتژی تلاش مجدد با یک عقبنشینی نمایی پیادهسازی کنید. پس از اولین شکست، با یک تأخیر اولیه ۵ ثانیهای قبل از تلاش مجدد شروع کنید.
یک استراتژی تلاش مجدد با حداکثر تعداد تلاش به عنوان شرط خروج با استفاده از یک تأخیر نمایی افزایش یافته در هر بار (10 ثانیه، 20 ثانیه و غیره) پیادهسازی کنید.
تعامل کاربر را در طول نصب برنامه ADP ردیابی کنید
اگر دستگاه نیاز به نصب برنامه ADP در طول prepareEnvironment داشته باشد، برنامه شما میتواند تعامل کاربر را با پیادهسازی NotificationReceiverService برای دریافت اعلانهایی که getPrepareEnvironmentListener لغو میکنند، پیگیری کند:
کاتلین
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 } }
جاوا
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"); } } }
مشکلات شناخته شده
در حال حاضر هیچ مشکل شناختهشدهای وجود ندارد.