המסמך הזה אמור לשמש כמדריך הראשי לשימוש ב-AMAPI SDK לצורך קבלת אותות אמון מהמכשיר.
ערכת ה-SDK של AMAPI מאפשרת לאפליקציה שלכם (שנקראת לפעמים 'אפליקציית שותף') לגשת לאותות האמון של המכשיר מאפליקציית ADP (Android Device Policy). לאחר מכן, האפליקציה יכולה להשתמש באותם אותות כדי לחשב את מצב האמון של המכשיר ולהפעיל את הלוגיקה העסקית שנבחרה.
דרישות מוקדמות
- הגישה לאותות האמינות של המכשיר מוגבלת כדי למנוע שימוש לא מורשה. מידע על תהליך הגשת הבקשה זמין בדף גישה לסמלי האמון של המכשיר.
- ב-Android Enterprise מומלץ לשלב את חבילת ממשקי ה-API של Play Integrity באפליקציית הלקוח, ולהתייחס לתוצאה לפני קריאת אותות האמון של המכשיר והסתמכות עליהם. אין לסמוך על מכשירים שלא עומדים בבדיקות של Play Integrity API, או על אותות שמקורם במכשיר שמשמש לקביעת מצב האמון. פרטים נוספים זמינים במסמכי התיעוד של Play Integrity.
שילוב עם AMAPI SDK באפליקציה
כדי לגשת לאותות האמון של המכשיר, האפליקציה צריכה לשלב את AMAPI SDK. מידע נוסף על הספרייה הזו ועל האופן שבו מוסיפים אותה לאפליקציה זמין במדריך לשילוב AMAPI SDK.
הוספת ההרשאות הנדרשות
כדי לקבל חלק מהאותות שמוחזרים מ-Device Trust מ-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
כדי לגשת לאותות האמון של המכשיר, אם הסביבה מוכנה ועדכנית (ראו גישה לאותות האמון של המכשיר).
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()); }
אם אפליקציית ADP מותקנת אבל לא עדכנית, האפליקציה שלכם צריכה לבצע קריאה ל-prepareEnvironment
כדי לעדכן את אפליקציית ADP בשקט, ללא התערבות של המשתמש.
אם אפליקציית ADP לא מותקנת, האפליקציה שלכם יכולה להפעיל את prepareEnvironment
כדי לבקש מהמשתמש להתקין את אפליקציית ADP. תוכלו לקרוא מידע נוסף במאמר הכנת סביבת הלקוח.
הכנת סביבת הלקוח
אם אפליקציית ADP כבר מותקנת, ה-API יעדכן אותה באופן אוטומטי בלי התערבות של המשתמש.
אם אפליקציית ADP לא מותקנת, ה-API יבקש מהמשתמש לאשר את התקנת אפליקציית ADP.
אפשר להירשם לשיחה חוזרת כדי לעקוב אחרי הבחירה של המשתמש. פרטים נוספים זמינים במאמר מעקב אחר אינטראקציות של משתמשים במהלך התקנת אפליקציית ADP.
מומלץ לבצע את הקריאה ל-prepareEnvironment
מתהליך בחזית, במהלך תהליך ההצטרפות לחוויית המשתמש, כדי למנוע הפתעה של המשתמש בתיבת הדו-שיח המודולרית Install Android Device Policy.
אם לא ניתן לבצע קריאה מתהליך בחזית המסך כי מדובר בתהליך אינטרנט ולרכיב Android אין ממשק משתמש, מותר לבצע קריאה מהרקע, בתנאי שהיא מתבצעת במהלך תהליך ההצטרפות לחוויית המשתמש.
אחרי שהסביבה מוגדרת בצורה נכונה, אפשר לגשת לאותות האמון של המכשיר. גישה לאותות האמינות של המכשיר
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()); }
גישה לאותות אמון של מכשירים
כדי לגשת לאותות האמון של המכשיר שמעניינים אתכם, תוכלו להשתמש במכונה deviceClient
שצוינה בשלב הקודם כדי לבקש את האובייקט 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()); }
מעקב אחר האינטראקציה של המשתמשים במהלך התקנת אפליקציית ADP
אם המכשיר צריך להתקין את אפליקציית ADP במהלך prepareEnvironment
, האפליקציה שלכם יכולה לעקוב אחרי האינטראקציה של המשתמש באמצעות הטמעת NotificationReceiverService
כדי לקבל התראות שמבטלות את 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"); } } }
בעיות מוכרות
אין כרגע בעיות ידועות.