تتيح ميزة "أدوار التطبيق" لمشرف تكنولوجيا المعلومات منح امتيازات خاصة لتطبيق مُدار على جهاز يعمل بنظام التشغيل Android. من خلال تعيين دور محدّد، يمكن إعفاء التطبيق من قيود الطاقة والقيود المفروضة على التشغيل في الخلفية والتعليق والتسبُّت (على الإصدار 14 من نظام التشغيل Android والإصدارات الأحدث) وإيقاف عناصر التحكّم الخاصة بالمستخدم (أي تضمين إجراءات المستخدم مثل الإيقاف الإجباري ومحو بيانات التطبيق) (على الإصدار 11 من نظام التشغيل Android والإصدارات الأحدث)، ما يسمح له بتنفيذ وظيفته الأساسية بدون انقطاع. بالإضافة إلى ذلك، يمكن إشعار التطبيق بالأدوار المخصّصة له، ما يسمح له ببدء التشغيل تلقائيًا بدون تدخل المستخدم.
للاطّلاع على قائمة بأدوار التطبيق المتاحة والامتيازات الخاصة الممنوحة لكل دور، راجِع RoleType.
المتطلبات الأساسية
تتم إدارة الجهاز من خلال إدارة الخدمات الجوّالة للمؤسسات (EMM) المستندة إلى AMAPI (لا تتوافق إدارة الخدمات الجوّالة للمؤسسات التي تستخدم أداة DPC مخصّصة).
إعداد تطبيقك لاستخدام الميزة
لا يكون التكامل مع حزمة تطوير البرامج (SDK) الخاصة بواجهة برمجة التطبيقات AMAPI مطلوبًا إلا إذا كان التطبيق يريد تلقّي إشعارات بشأن الأدوار المخصّصة له، ما يتيح له بدء التشغيل تلقائيًا (أي التشغيل التلقائي بدون تفاعل المستخدم).
الدمج مع حزمة تطوير البرامج (SDK) لواجهة برمجة التطبيقات AMAPI في تطبيقك
يمكنك العثور على مزيد من المعلومات حول حزمة تطوير البرامج (SDK) لواجهة AMAPI وكيفية إضافتها إلى تطبيقك في دليل دمج حزمة تطوير البرامج (SDK) لواجهة AMAPI.
إضافة البيانات الوصفية المطلوبة إلى بيان التطبيق
يحتاج تطبيق Android Device Policy (ADP) إلى معرفة ComponentName لفئتك
التي تنفّذ NotificationReceiverService لإعلام تطبيقك بالأدوار
المخصّصة له. يجب تصنيف خدمتك في AndroidManifest.xml بشكل مناسب
لكي يتمكّن ADP من اكتشافها تلقائيًا.
- يجب أن يتضمّن تطبيقك خدمة واحدة فقط وهي
enabled، وأن تتضمّنmeta-dataبقيمةandroid:nameتساويcom.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES - يجب أن تكون قيمة
android:exportedفي هذه الخدمة هيtrue - يجب ضبط
android:valueالخاص بـmeta-dataعلى سلسلة فارغة
<service
android:name=".MyNotificationReceiverService"
android:exported="true">
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES" android:value="" />
</service>
إذا كنت تختبر دور COMPANION_APP، عليك أيضًا إضافة meta-data التالي إلى خدمتك حتى يتمكّن تطبيق Android Device Policy من إرسال تحديثات حالة الأوامر المحلية إلى تطبيقك:
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_COMMAND_STATUS" android:value="" />
إنشاء خدمة توسّع NotificationReceiverService (أو تعديل الخدمة الحالية)
أنشئ NotificationReceiverService أو عدِّله، ونفِّذ AppRolesListener للاستماع إلى الأدوار المخصّصة لتطبيقك. getAppRolesListener() فقط مطلوب للاستماع إلى الأدوار المخصّصة لتطبيقك. إذا تم تخصيص دور COMPANION_APP لتطبيقك، عليك أيضًا تنفيذ getCommandListener():
import android.util.Log
import com.google.android.managementapi.approles.AppRolesListener
import com.google.android.managementapi.approles.model.AppRolesSetRequest
import com.google.android.managementapi.approles.model.AppRolesSetResponse
import com.google.android.managementapi.commands.CommandListener
import com.google.android.managementapi.commands.model.Command
import com.google.android.managementapi.notification.NotificationReceiverService
class MyNotificationReceiverService : NotificationReceiverService() {
// If your app wants to listen for roles assigned
override fun getAppRolesListener(): AppRolesListener =
object : AppRolesListener {
override fun onAppRolesSet(request: AppRolesSetRequest): AppRolesSetResponse {
val roleTypes = request.roles.map { role -> role.roleType }
Log.i(TAG, "onAppRolesSet: $roleTypes")
return AppRolesSetResponse.getDefaultInstance()
}
}
// If your app wants to listen for local command status updates
// Only relevant for COMPANION_APP role
override fun getCommandListener(): CommandListener {
return object : CommandListener {
override fun onCommandStatusChanged(command: Command) {
Log.i(TAG, "onCommandStatusChanged")
}
}
}
private companion object {
const val TAG = "MyNotificationReceiverService"
}
}
يمكن إرسال إشعارات إلى تطبيقك عدة مرات إذا تغيّرت أدواره عدة مرات. في حال إزالة جميع الأدوار، سيظل تطبيقك يتلقّى إشعارًا يتضمّن قائمة فارغة بالأدوار. سيؤدي هذا الإشعار إلى إخراج تطبيقك من حالة الإيقاف، وسيتمكّن تطبيقك من بدء التشغيل بدون أي تفاعل من المستخدم، وذلك بالإضافة إلى الاستثناءات الممنوحة لتطبيقك. بفضل إشعار أدوار التطبيق والاستثناءات، يمكن لتطبيقك الاستماع إلى عمليات البث ACTION_BOOT_COMPLETED. إذا كان تطبيقك يعتمد على الإعدادات المُدارة لتشغيله، يمكنك الاطّلاع على إعداد الإعدادات المُدارة لمعرفة كيفية قراءة التغييرات والاستماع إليها.
توفير الجهاز مع سياسات أدوار التطبيق
يمكن لمطوّري التطبيقات اختبار منح أدوار التطبيق لتطبيقاتهم باستخدام إدارة الخدمات الجوّالة للمؤسسات (EMM) أو اتّباع دليل البدء السريع لواجهة Android Management API. تتيح لك ورقة ملاحظات AMAPI Colab تسجيل مؤسسة وإنشاء سياسة وتوفير جهاز.
تحديد سياسة تطبيقك باستخدام أدوار التطبيق
إعداد policy باستخدام أدوار التطبيق التي من المفترض أن يتضمّنها تطبيقك باستخدام
ApplicationPolicy.roles
يوضّح المثال التالي كيفية ضبط الدور لتطبيقات MTD:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
قبل منح الأدوار المحدّدة في السياسة، سيتحقّق النظام من أنّ بصمة شهادة مفتاح توقيع التطبيق على الجهاز تتطابق مع تلك الموجودة في "متجر Play".
إذا كانت بصمة الإصبع مختلفة، لن يتم منح الأدوار للتطبيق، وسيتم إبلاغ إدارة الخدمات الجوّالة للمؤسسات (EMM) بعدم الامتثال NonComplianceReason.APP_SIGNING_CERT_MISMATCH.
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"signingKeyCerts": [
{ "signingKeyCertFingerprintSha256": "base64-encoded-sha256" }
],
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
إذا كان تطبيقك يتضمّن إعدادات مُدارة، يمكن لمشرف تكنولوجيا المعلومات إعداد
إعدادات أولية restriction ذات الصلة في سياسة التطبيق:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
],
"managedConfiguration": {
"<key>": "<value>"
}
}
]
}