إعادة التوجيه إلى "مركز الأمان"
يمكن لأي تطبيق فتح "مركز الأمان" باستخدام إجراء android.content.Intent.ACTION_SAFETY_CENTER
(قيمة السلسلة
android.intent.action.SAFETY_CENTER
).
لفتح "مركز الأمان"، يمكنك إجراء مكالمة من داخل مثيل Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
إعادة التوجيه إلى مشكلة معيّنة
ويمكن أيضًا إعادة التوجيه إلى بطاقة تحذير محددة في "مركز الأمان" باستخدام عناصر إضافية محدّدة الغرض. ليس من المفترض أن تستخدم الجهات الخارجية هذه الميزات الإضافية،
لذا فهي جزء من SafetyCenterManager
، الذي يشكّل جزءًا من @SystemApi
. لا يمكن سوى
لتطبيقات النظام الوصول إلى هذه الإضافات.
عناصر إضافية للنوايا التي تعيد توجيه بطاقة تحذير معيّنة:
EXTRA_SAFETY_SOURCE_ID
- قيمة السلسلة:
android.safetycenter.extra.SAFETY_SOURCE_ID
- نوع السلسلة: تحدّد معرّف مصدر الأمان لبطاقة التحذير المرتبطة
- مطلوب لكي تنجح إعادة التوجيه إلى المشكلة.
- قيمة السلسلة:
EXTRA_SAFETY_SOURCE_ISSUE_ID
- قيمة السلسلة:
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- نوع السلسلة: يحدِّد معرّف بطاقة التحذير
- مطلوب لكي تنجح إعادة التوجيه إلى المشكلة.
- قيمة السلسلة:
EXTRA_SAFETY_SOURCE_USER_HANDLE
- قيمة السلسلة:
android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
- النوع
UserHandle
: يحدّدUserHandle
لبطاقة التحذير المرتبطة - اختيارية (القيمة التلقائية هي المستخدم الحالي)
- قيمة السلسلة:
يمكن استخدام مقتطف الرمز البرمجي أدناه من داخل مثيل Activity
لفتح
شاشة "مركز السلامة" على مشكلة معيّنة:
UserHandle theUserHandleThisIssueCameFrom = …;
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_ID, "TheSafetySourceIdThisIssueCameFrom")
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID, "TheSafetySourceIssueIdToRedirectTo")
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_USER_HANDLE, theUserHandleThisIssueCameFrom);
startActivity(openSafetyCenterIntent);
إعادة التوجيه إلى صفحة فرعية محدّدة (بدءًا من Android 14)
في الإصدار 14 من نظام التشغيل Android أو الإصدارات الأحدث، يتم تقسيم صفحة "مركز الأمان"
إلى صفحات فرعية متعددة تمثّل SafetySourcesGroup
المختلفة (في
الإصدار 13 من نظام التشغيل Android، يتم عرض ذلك كإدخالات قابلة للطي).
من الممكن إعادة التوجيه إلى صفحة فرعية معيّنة باستخدام هذا الغرض الإضافي:
EXTRA_SAFETY_SOURCES_GROUP_ID
- قيمة السلسلة:
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- نوع السلسلة: تحدّد رقم تعريف السمة
SafetySourcesGroup
- مطلوبة لكي تعمل إعادة التوجيه إلى الصفحة الفرعية
- قيمة السلسلة:
يمكن استخدام مقتطف الرمز أدناه من داخل مثيل Activity
لفتح
شاشة "مركز الأمان" على صفحة فرعية محدّدة:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");
startActivity(openSafetyCenterIntent);
استخدام واجهات برمجة تطبيقات مصدر "مركز الأمان"
تتوفّر واجهات برمجة التطبيقات المصدر في "مركز الأمان" باستخدام
SafetyCenterManager
(وهو @SystemApi
)، ويتوفّر رمز واجهة برمجة التطبيقات في
البحث في الرموز.
يتوفر رمز تنفيذ واجهات برمجة التطبيقات في Code Search.
الأذونات
لا يمكن الوصول إلى واجهات برمجة التطبيقات المصدر في "مركز الأمان" إلا من خلال تطبيقات النظام المُدرَجة في القائمة المسموح بها باستخدام الأذونات المدرَجة أدناه. لمزيد من المعلومات، يُرجى الاطّلاع على قائمة السماح بالوصول إلى أذونات المزايا المميّزة.
READ_SAFETY_CENTER_STATUS
signature|privileged
- يتم استخدامها لواجهة برمجة تطبيقات
SafetyCenterManager#isSafetyCenterEnabled()
(لا حاجة إلى المصادر في مركز الأمان، إنّها تحتاج فقط إلى إذنSEND_SAFETY_CENTER_UPDATE
) - تستخدمه تطبيقات النظام التي تتحقّق من تفعيل "مركز الأمان".
- تم منح الإذن لتطبيقات النظام المُدرَجة في القائمة المسموح بها فقط
SEND_SAFETY_CENTER_UPDATE
internal|privileged
- تُستخدَم لواجهة برمجة التطبيقات المفعَّلة وواجهة برمجة التطبيقات Safety Sources API.
- تُستخدَم من قِبل مصادر الأمان فقط
- تم منح الإذن لتطبيقات النظام المُدرَجة في القائمة المسموح بها فقط
هذه الأذونات مميّزة ولا يمكنك الحصول عليها إلا من خلال إضافتها إلى
الملف ذي الصلة، على سبيل المثال،ملف
com.android.settings.xml
لتطبيق "الإعدادات" وملفAndroidManifest.xml
للتطبيق. يمكنك الانتقال إلى
protectionLevel
للحصول على مزيد من المعلومات حول نموذج الأذونات.
الحصول على SafetyCenterManager
SafetyCenterManager
هي فئة @SystemApi
يمكن الوصول إليها من تطبيقات النظام
بدءًا من Android 13. توضح هذه المكالمة كيفية الحصول
على SafetyCenterManager:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
// Must be on T or above to interact with Safety Center.
return;
}
SafetyCenterManager safetyCenterManager = context.getSystemService(SafetyCenterManager.class);
if (safetyCenterManager == null) {
// Should not be null on T.
return;
}
التأكّد من تفعيل "مركز الأمان"
تتحقّق هذه الدعوة ممّا إذا كان تطبيق "مركز الأمان" مفعّلاً. تتطلّب المكالمة الحصول على إذن
READ_SAFETY_CENTER_STATUS
أو SEND_SAFETY_CENTER_UPDATE
:
boolean isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled();
if (isSafetyCenterEnabled) {
// …
} else {
// …
}
تقديم البيانات
يتم تقديم بيانات مصدر "مركز الأمان" التي تحتوي على String sourceId
المحدّد إلى "مركز
الأمان" باستخدام العنصر SafetySourceData
الذي يمثّل إدخال واجهة مستخدِم وقائمة بالمشاكل (بطاقات التحذير). يمكن أن يتضمّن إدخال واجهة المستخدم وبطاقات التحذير
مستويات خطورة مختلفة محدّدة في فئة SafetySourceData
:
SEVERITY_LEVEL_UNSPECIFIED
- لم يتم تحديد درجة خطورة
- اللون: رمادي أو شفاف (حسب
SafetySourcesGroup
للملف الشخصي) - يتم استخدامها للبيانات الديناميكية التي تظهر كإدخال ثابت في واجهة المستخدم أو لإظهار إدخال غير محدد
- يجب عدم استخدامها في البطاقات التحذيرية
SEVERITY_LEVEL_INFORMATION
- معلومات أساسية أو اقتراح بسيط
- اللون: أخضر
SEVERITY_LEVEL_RECOMMENDATION
- التوصية بأن يتخذ المستخدم إجراءً بشأن هذه المشكلة، لأنها قد تعرِّضه للخطر
- اللون: أصفر
SEVERITY_LEVEL_CRITICAL_WARNING
- تحذير خطير يُطلب من المستخدم اتّخاذ إجراء بشأن هذه المشكلة لأنّها تشكل خطرًا
- اللون: أحمر
SafetySourceData
يتألف الكائن SafetySourceData
من إدخال في واجهة المستخدم وبطاقات تحذير ومتغيرات ثابتة.
- مثال
SafetySourceStatus
اختياري (إدخال في واجهة المستخدم) - قائمة بمثيلات عددها
SafetySourceIssue
(بطاقات تحذير) - مزايا إضافية اختيارية بقيمة
Bundle
(بدءًا من 14) - القيم الثابتة:
- يجب أن تتألف قائمة
SafetySourceIssue
من مشاكل ذات معرّفات فريدة. - يجب ألا تكون قيمة المثيل
SafetySourceIssue
ذات أهمية أكبر منSafetySourceStatus
في حال توفّرها (ما لم تكن السمةSafetySourceStatus
SEVERITY_LEVEL_UNSPECIFIED
، وفي هذه الحالة يُسمح بـSEVERITY_LEVEL_INFORMATION
). - يجب استيفاء المتطلبات الإضافية التي تفرضها إعدادات واجهة برمجة التطبيقات. على سبيل المثال، إذا كان المصدر مخصّصًا للمشكلة فقط، يجب ألا يوفّر
مثيل
SafetySourceStatus
.
- يجب أن تتألف قائمة
SafetySourceStatus
- عنوان
CharSequence
مطلوب - ملخّص
CharSequence
مطلوب - مستوى الخطورة المطلوب
- عنصر اختياري
PendingIntent
لإعادة توجيه المستخدم إلى الصفحة الصحيحة (يستخدم الإعداد التلقائيintentAction
من الإعدادات، إن توفّرت) - علامة
IconAction
اختيارية (تظهر كرمز جانبي على الإدخال) وتتألف من:- نوع الرمز المطلوب، والذي يجب أن يكون أحد الأنواع التالية:
ICON_TYPE_GEAR
: يظهر كعجلة بجانب إدخال واجهة المستخدمICON_TYPE_INFO
: يتم عرضها كرمز معلومات بجانب إدخال واجهة المستخدم.
- مطلوب
PendingIntent
لإعادة توجيه المستخدم إلى صفحة أخرى
- نوع الرمز المطلوب، والذي يجب أن يكون أحد الأنواع التالية:
- قيمة
enabled
منطقية اختيارية تسمح بوضع علامة على إدخال واجهة المستخدم بأنّه غير مفعّل، وبالتالي لا يمكن النقر عليه (القيمة التلقائية هيtrue
) - المتغيّرات:
- يجب أن تفتح نُسخ
PendingIntent
نسخةActivity
. - إذا كان الإدخال غير مفعّل، يجب تحديده
SEVERITY_LEVEL_UNSPECIFIED
. - المتطلبات الإضافية التي تفرضها إعدادات واجهة برمجة التطبيقات
- يجب أن تفتح نُسخ
SafetySourceIssue
- معرّف
String
الفريد المطلوب - عنوان
CharSequence
مطلوب - ترجمة اختيارية باللغة
CharSequence
- ملخّص
CharSequence
مطلوب - مستوى الخطورة المطلوب
- فئة المشكلة الاختيارية، والتي يجب أن تكون إحدى الفئات التالية:
ISSUE_CATEGORY_DEVICE
: تؤثر المشكلة في جهاز المستخدم.ISSUE_CATEGORY_ACCOUNT
: تؤثر المشكلة في حسابات المستخدم.ISSUE_CATEGORY_GENERAL
: تؤثر المشكلة في الأمان العام للمستخدم. هذا هو الخيار التلقائي.ISSUE_CATEGORY_DATA
(بدءًا من الإصدار 14 من نظام Android): تؤثر المشكلة في بيانات المستخدم.ISSUE_CATEGORY_PASSWORDS
(اعتبارًا من نظام التشغيل Android 14): تؤثر المشكلة في كلمات مرور المستخدمين.ISSUE_CATEGORY_PERSONAL_SAFETY
(بدءًا من Android 14): تؤثر المشكلة في السلامة الشخصية للمستخدم.
- قائمة بعناصر
Action
التي يمكن للمستخدم استخدامها لهذه المشكلة، وتتألّف كل مثيلAction
مما يلي:- معرّف
String
الفريد المطلوب - تصنيف
CharSequence
مطلوب - مطلوب
PendingIntent
لإعادة توجيه المستخدم إلى صفحة أخرى أو معالجة الإجراء مباشرةً من شاشة "مركز الأمان" - قيمة منطقية اختيارية لتحديد ما إذا كان من الممكن حلّ هذه المشكلة من شاشة "مركز الأمان" مباشرةً (القيمة التلقائية هي
false
) CharSequence
رسالة اختيارية للنجاح، يتم عرضها للمستخدم عند حلّ المشكلة بنجاح مباشرةً من شاشة "مركز السلامة"
- معرّف
- اختياري
PendingIntent
يتم طلبه عندما يرفض المستخدم المشكلة (الإعداد التلقائي هو "لا شيء") - معرّف نوع المشكلة
String
المطلوب. هذا المعرّف مشابه لمعرّف المشكلة، ولكن ليس من الضروري أن يكون فريدًا ويُستخدَم في التسجيل. - وسمة
String
اختيارية لمعرّف إزالة التكرار، تتيح هذه السمة نشرSafetySourceIssue
نفسها من مصادر مختلفة وعرضها مرة واحدة فقط في واجهة المستخدم على افتراض أنّها تستخدم السمةdeduplicationGroup
نفسها (بدءًا من Android 14). إذا لم يتم تحديد المشكلة، لن تتم إزالة تكرارها CharSequence
اختياري لعنوان الإسناد، وهو نص يعرض مصدر بطاقة التحذير (بدءًا من Android 14). وفي حال عدم تحديد قيمة، يتم استخدام عنوانSafetySourcesGroup
.- إمكانية معالجة المشكلة (اختيارية، بدءًا من Android 14)،
يجب أن تكون أحد الخيارَين التاليَين:
ISSUE_ACTIONABILITY_MANUAL
: على المستخدم حلّ هذه المشكلة يدويًا هذا هو الخيار التلقائي.ISSUE_ACTIONABILITY_TIP
: هذه المشكلة مجرد نصيحة وقد لا تتطلّب أي تدخل من المستخدم.ISSUE_ACTIONABILITY_AUTOMATIC
: سبق أن تم اتخاذ إجراء بشأن هذه المشكلة وقد لا تحتاج إلى إدخال أي بيانات من المستخدم.
- سلوك الإشعارات الاختياري (بدءًا من Android
14)، والذي يجب أن يكون أحد الخيارَين التاليَين:
NOTIFICATION_BEHAVIOR_UNSPECIFIED
: سيقرر "مركز الأمان" ما إذا كان يجب إرسال إشعار بشأن بطاقة التحذير. هذا هو الخيار التلقائي.NOTIFICATION_BEHAVIOR_NEVER
: لا يتم نشر أي إشعار.NOTIFICATION_BEHAVIOR_DELAYED
: يتم نشر إشعار بعد فترة من الإبلاغ عن المشكلة لأول مرة.NOTIFICATION_BEHAVIOR_IMMEDIATELY
: يتم نشر إشعار فور الإبلاغ عن المشكلة.
- اختياري
Notification
، لعرض إشعار مخصّص مع بطاقة التحذير (بدءًا من Android 14) إذا لم يتم تحديد قيمة، يتم اشتقاق القيمةNotification
من بطاقة التحذير. تتكوّن من:- عنوان
CharSequence
مطلوب - ملخّص
CharSequence
مطلوب - قائمة بعناصر
Action
التي يمكن للمستخدم الاستعانة بها لهذا الإشعار
- عنوان
- المتغيّرات:
- يجب أن تتألف قائمة نُسخ
Action
من إجراءات لها معرّفات فريدة. - يجب أن تحتوي قائمة نُسخ
Action
على عنصرAction
واحد أو عنصرَين. إذا لم تكن إمكانية اتّخاذ إجراء هيISSUE_ACTIONABILITY_MANUAL
، يُسمح بقيمة صفر لسمةAction
. - يجب ألا يفتح الإجراء OnDismiss
PendingIntent
مثيلActivity
. - المتطلبات الإضافية المفروضة من خلال إعدادات واجهة برمجة التطبيقات
- يجب أن تتألف قائمة نُسخ
يتم تقديم البيانات إلى "مركز الأمان" عند رصد أحداث معيّنة، لذا من الضروري تحديد السبب الذي دفع المصدر إلى تزويد "SafetySourceData
" بمثيل SafetyEvent
.
SafetyEvent
- النوع المطلوب، والذي يجب أن يكون واحدًا مما يلي:
SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
: تغيّرت حالة المصدر.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
: للردّ على إشارة تحديث أو إعادة فحص من "مركز الأمان"، استخدِم هذا الخيار بدلاً منSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
كي يتمكّن "مركز الأمان" من تتبُّع طلب إعادة التحميل أو إعادة الفحص.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
: تم حلّ المشكلة المتعلّقة بحالةSafetySourceIssue.Action
مباشرةً من شاشة "مركز الأمان". يُرجى استخدام هذا الرمز بدلاً منSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
ليتمكّن "مركز الأمان" من تتبُّع حالةSafetySourceIssue.Action
التي يتم حلّها.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
: حاولنا حلّ المشكلة المتعلّقة بحالةSafetySourceIssue.Action
مباشرةً من شاشة "مركز الأمان"، ولكن تعذّر علينا ذلك. يُرجى استخدام هذا الإجراء بدلاً منSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
ليتمكّن "مركز الأمان" من تتبُّع حالةSafetySourceIssue.Action
بعد تعذُّر حلّها.SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED
: تم تغيير لغة الجهاز، وبالتالي نحن بصدد تعديل نص البيانات المقدَّمة، ويُسمح باستخدامSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
لهذا الغرض.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
: نوفّر هذه البيانات كجزء من عملية التشغيل الأولية لأنّ بيانات "مركز الأمان" لا تبقى محفوظة عند إعادة التشغيل، ويُسمح باستخدامSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
لهذا الغرض.
- معرّف
String
اختياري لمعرّف البث لإعادة التحديث - معرّف
String
الاختياري لمثيلSafetySourceIssue
الذي يتم حله. - معرّف
String
اختياري لمثيلSafetySourceIssue.Action
الذي يتم حلّه - المتغيّرات:
- يجب تقديم معرّف البث لإعادة التحديث إذا كان النوع هو
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
. - يجب تقديم رقمَي تعريف المشكلة والإجراءات إذا كان النوع
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
أوSAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
.
- يجب تقديم معرّف البث لإعادة التحديث إذا كان النوع هو
وفي ما يلي مثال على كيفية تقديم أحد المصادر للبيانات إلى "مركز الأمان" (في هذه الحالة، يقدّم إدخالاً ببطاقة تحذير واحدة):
PendingIntent redirectToMyScreen =
PendingIntent.getActivity(
context, requestCode, redirectToMyScreenIntent, PendingIntent.FLAG_IMMUTABLE);
SafetySourceData safetySourceData =
new SafetySourceData.Builder()
.setStatus(
new SafetySourceStatus.Builder(
"title", "summary", SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
.setPendingIntent(redirectToMyScreen)
.build())
.addIssue(
new SafetySourceIssue.Builder(
"MyIssueId",
"title",
"summary",
SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
"MyIssueTypeId")
.setSubtitle("subtitle")
.setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
.addAction(
new SafetySourceIssue.Action.Builder(
"MyIssueActionId", "label", redirectToMyScreen)
.build())
.build())
.build();
SafetyEvent safetyEvent = new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
safetyCenterManager.setSafetySourceData("MySourceId", safetySourceData, safetyEvent);
الحصول على آخر البيانات المقدَّمة
يمكنك الحصول على آخر البيانات المقدَّمة إلى "مركز الأمان" لمصدر يملكه
تطبيقك. ويمكنك استخدام هذه البيانات لعرض محتوى في واجهة المستخدم الخاصة بك، أو للتحقّق مما إذا كان يجب تعديل البيانات
قبل تنفيذ عملية باهظة التكلفة، أو لتقديم مثيل SafetySourceData
نفسه إلى "مركز الأمان" مع بعض التغييرات أو مثيل SafetyEvent
جديد. وهو مفيد أيضًا للاختبار.
استخدِم هذا الرمز للحصول على آخر البيانات المقدَّمة إلى "مركز الأمان":
SafetySourceData lastDataProvided =
safetyCenterManager.getSafetySourceData("MySourceId");
الإبلاغ عن خطأ
إذا لم تتمكّن من جمع بيانات SafetySourceData
، يمكنك الإبلاغ عن الخطأ في Safety
Center، ما يؤدي إلى تغيير الإدخال إلى اللون الرمادي، وحذف البيانات المخزّنة مؤقتًا، وعرض
رسالة مثل تعذّر التحقّق من الإعداد. يمكنك أيضًا الإبلاغ عن خطأ إذا تعذّر حلّ إحدى مثيلات SafetySourceIssue.Action
، وفي هذه الحالة، لا يتم محو البيانات المخزّنة مؤقتًا ولا يتم تغيير إدخال واجهة المستخدم، ولكن يتم عرض رسالة للمستخدم لإعلامه بحدوث خطأ.
يمكنك تقديم الخطأ باستخدام SafetySourceErrorDetails
، الذي يتألف مما يلي:
SafetySourceErrorDetails
: مثيلSafetyEvent
مطلوب:
// An error has occurred in the background, need to clear the Safety Center data to avoid showing data that may not be valid anymore
SafetyEvent safetyEvent = new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
SafetySourceErrorDetails safetySourceErrorDetails = new SafetySourceErrorDetails(safetyEvent);
safetyCenterManager.reportSafetySourceError("MySourceId", safetySourceErrorDetails);
الرد على طلب تحديث أو إعادة فحص
يمكنك الحصول على إشارة من "مركز الأمان" لتقديم بيانات جديدة. من خلال الردّ على طلب إعادة تحميل البيانات أو إعادة الفحص، يتمكّن المستخدم من الاطّلاع على الحالة الحالية عند فتح "مركز الأمان" وعند النقر على زر الفحص.
ويتم ذلك من خلال تلقّي رسالة بث تتضمّن الإجراء التالي:
ACTION_REFRESH_SAFETY_SOURCES
- قيمة السلسلة:
android.safetycenter.action.REFRESH_SAFETY_SOURCES
- يتم تشغيله عندما يرسل "مركز الأمان" طلبًا لإعادة تحميل بيانات مصدر الأمان لتطبيق معيّن
- نية محمية لا يمكن إرسالها إلا من خلال النظام
- يتم إرسالها إلى جميع مصادر الأمان في ملف الإعداد كنية صريحة
ويجب الحصول على إذن
SEND_SAFETY_CENTER_UPDATE
- قيمة السلسلة:
يتم توفير الميزات الإضافية التالية كجزء من هذا البث:
EXTRA_REFRESH_SAFETY_SOURCE_IDS
- قيمة السلسلة:
android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
- يمثّل نوع مصفوفة السلسلة (
String[]
) أرقام تعريف المصدر المطلوب إعادة تحميلها للتطبيق المحدّد.
- قيمة السلسلة:
EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- قيمة السلسلة:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- نوع عدد صحيح، يمثّل نوع الطلب
@IntDef
- يجب أن تكون إحدى القيمتَين التاليتَين:
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
: يطلب من المصدر تقديم بيانات بسرعة نسبيًا، عادةً عندما يفتح المستخدم الصفحةEXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA
: يطلب من المصدر تقديم بيانات حديثة قدر الإمكان، عادةً عندما يضغط المستخدم على زر إعادة الفحص
- قيمة السلسلة:
EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
- قيمة السلسلة:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
- نوع السلسلة، يمثّل معرّفًا فريدًا لإعادة التحميل المطلوبة
- قيمة السلسلة:
للحصول على إشارة من "مركز السلامة"، عليك تنفيذ مثيل
BroadcastReceiver
. يتم إرسال البث باستخدام BroadcastOptions
خاص يسمح
للمستلِم ببدء خدمة تعمل في المقدّمة.
يستجيب BroadcastReceiver
لطلب إعادة التحميل:
public final class SafetySourceReceiver extends BroadcastReceiver {
// All the safety sources owned by this application.
private static final String[] ALL_SAFETY_SOURCES = new String[] {"MySourceId1", "…"};
@Override
public void onReceive(Context context, Intent intent) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
// Must be on T or above to interact with Safety Center.
return;
}
String action = intent.getAction();
if (!SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES.equals(action)) {
return;
}
String refreshBroadcastId =
intent.getStringExtra(SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID);
if (refreshBroadcastId == null) {
// Should always be provided.
return;
}
String[] sourceIds =
intent.getStringArrayExtra(SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCE_IDS);
if (sourceIds == null) {
sourceIds = ALL_SAFETY_SOURCES;
}
int requestType =
intent.getIntExtra(
SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE,
SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA);
SafetyCenterManager safetyCenterManager = context.getSystemService(SafetyCenterManager.class);
if (safetyCenterManager == null) {
// Should not be null on T.
return;
}
if (!safetyCenterManager.isSafetyCenterEnabled()) {
// Preferably, no Safety Source code should be run if Safety Center is disabled.
return;
}
SafetyEvent refreshSafetyEvent =
new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
.setRefreshBroadcastId(refreshBroadcastId)
.build();
for (String sourceId : sourceIds) {
SafetySourceData safetySourceData = getSafetySourceDataFor(sourceId, requestType);
// Set the data (or report an error with reportSafetySourceError, if something went wrong).
safetyCenterManager.setSafetySourceData(sourceId, safetySourceData, refreshSafetyEvent);
}
}
private SafetySourceData getSafetySourceDataFor(String sourceId, int requestType) {
switch (requestType) {
case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA:
return getRefreshSafetySourceDataFor(sourceId);
case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA:
return getRescanSafetySourceDataFor(sourceId);
default:
}
return getRefreshSafetySourceDataFor(sourceId);
}
// Data to provide when the user opens the page or on specific events.
private SafetySourceData getRefreshSafetySourceDataFor(String sourceId) {
// Get data for the source, if it's a fast operation it could potentially be executed in the
// receiver directly.
// Otherwise, it must start some kind of foreground service or expedited job.
return null;
}
// Data to provide when the user pressed the rescan button.
private SafetySourceData getRescanSafetySourceDataFor(String sourceId) {
// Could be implemented the same way as getRefreshSafetySourceDataFor, depending on the source's
// need.
// Otherwise, could potentially perform a longer task.
// In which case, it must start some kind of foreground service or expedited job.
return null;
}
}
تمّ الإعلان عن العنصر نفسه من BroadcastReceiver
في المثال أعلاه في
AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="…">
<application>
<!-- … -->
<receiver android:name=".SafetySourceReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES"/>
</intent-filter>
</receiver>
<!-- … -->
</application>
</manifest>
في العادة، يتم تنفيذ مصدر "مركز الأمان" بالطريقة التي تستدعي
"SafetyCenterManager
" عند تغيير بياناته. لأسباب تتعلّق بحالة النظام، ننصح بالردّ على إشارة إعادة الفحص فقط (عندما ينقر المستخدم على زر الفحص)، وليس عندما يفتح المستخدم "مركز الأمان". إذا كانت هذه الوظيفة
مطلوبة، يجب ضبط الحقل refreshOnPageOpenAllowed="true"
في ملف الإعدادات
لكي يتلقّى المصدر البث الذي يتم إرساله في هذه الحالات.
الاستجابة لـ "مركز الأمان" عندما تكون مفعّلة أو غير مفعَّلة
يمكنك الاستجابة عند تفعيل "مركز السلامة" أو إيقافه باستخدام إجراء النية التالي:
ACTION_SAFETY_CENTER_ENABLED_CHANGED
- قيمة السلسلة:
android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
- يتم تشغيله عند تفعيل "مركز الأمان" أو إيقافه أثناء تشغيل الجهاز
- لم يتم استدعاؤه عند التشغيل (استخدِم
ACTION_BOOT_COMPLETED
لذلك) - الغرض المحمي الذي يمكن أن يرسله النظام فقط
- يتم إرسالها إلى جميع مصادر الأمان في ملف الإعدادات كهدف
صريح، ويتطلب ذلك الحصول على إذن
SEND_SAFETY_CENTER_UPDATE
. - تم إرساله كطلب ضمني يتطلب إذن
READ_SAFETY_CENTER_STATUS
- قيمة السلسلة:
يُعدّ إجراء النية هذا مفيدًا لتفعيل الميزات ذات الصلة بمركز الأمان أو إيقافها على الجهاز.
تنفيذ إجراءات الحل
إجراء الحل هو مثيل SafetySourceIssue.Action
يمكن للمستخدم
حلّه مباشرةً من شاشة "مركز الأمان". ينقر المستخدم على زر إجراء، ويتم تشغيل مثيل PendingIntent
على SafetySourceIssue.Action
الذي أرسله مصدر الأمان، ما يؤدي إلى حل المشكلة في الخلفية وإرسال إشعار إلى "مركز الأمان" عند انتهاء العملية.
لتنفيذ إجراءات حل المشكلة، يمكن لمصدر "مركز الأمان" استخدام خدمة إذا كان من المتوقّع أن تستغرق العملية بعض الوقت (PendingIntent.getService
) أو مستقبِل البث (PendingIntent.getBroadcast
).
يمكنك استخدام هذا الرمز لإرسال حل المشكلة إلى "مركز الأمان":
Intent resolveIssueBroadcastIntent =
new Intent("my.package.name.MY_RESOLVING_ACTION").setClass(ResolveActionReceiver.class);
PendingIntent resolveIssue =
PendingIntent.getBroadcast(
context, requestCode, resolveIssueBroadcastIntent, PendingIntent.FLAG_IMMUTABLE);
SafetySourceData safetySourceData =
new SafetySourceData.Builder()
.setStatus(
new SafetySourceStatus.Builder(
"title", "summary", SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
.setPendingIntent(redirectToMyScreen)
.build())
.addIssue(
new SafetySourceIssue.Builder(
"MyIssueId",
"title",
"summary",
SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
"MyIssueTypeId")
.setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
.addAction(
new SafetySourceIssue.Action.Builder(
"MyIssueActionId", "label", resolveIssue)
.setWillResolve(true)
.build())
.build())
.build();
SafetyEvent safetyEvent = new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
safetyCenterManager.setSafetySourceData("MySourceId", safetySourceData, safetyEvent);
BroadcastReceiver
يحل الإجراء:
public final class ResolveActionReceiver extends BroadcastReceiver {
private static final String MY_RESOLVING_ACTION = "my.package.name.MY_RESOLVING_ACTION";
@Override
public void onReceive(Context context, Intent intent) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
// Must be on T or above to interact with Safety Center.
return;
}
String action = intent.getAction();
if (!MY_RESOLVING_ACTION.equals(action)) {
return;
}
SafetyCenterManager safetyCenterManager = context.getSystemService(SafetyCenterManager.class);
if (safetyCenterManager == null) {
// Should not be null on T.
return;
}
if (!safetyCenterManager.isSafetyCenterEnabled()) {
// Preferably, no Safety Source code should be run if Safety Center is disabled.
return;
}
resolveTheIssue();
SafetyEvent resolveActionSafetyEvent =
new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED)
.setSafetySourceIssueId("MyIssueId")
.setSafetySourceIssueActionId("MyIssueActionId")
.build();
SafetySourceData dataWithoutTheIssue = …;
// Set the data (or report an error with reportSafetySourceError and
// SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED, if something went wrong).
safetyCenterManager.setSafetySourceData("MySourceId", dataWithoutTheIssue, resolveActionSafetyEvent);
}
private void resolveTheIssue() {
// Resolves the issue for the user. Given this a BroadcastReceiver, this should be a fast action.
// Otherwise, a foreground service and PendingIntent.getService should be used instead (or a job
// could be scheduled here, too).
}
}
تم تعريف مثيل BroadcastReceiver
نفسه في المثال أعلاه في AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="…">
<application>
<!-- … -->
<receiver android:name=".ResolveActionReceiver"
android:exported="false">
<intent-filter>
<action android:name="my.package.name.MY_RESOLVING_ACTION"/>
</intent-filter>
</receiver>
<!-- … -->
</application>
</manifest>
الردّ على رفض المشاكل
يمكنك تحديد مثيل PendingIntent
الذي يمكن تشغيله عند تجاهل مثيل SafetySourceIssue
. يتعامل مركز الأمان مع
عمليات إغلاق المشكلات التالية:
- إذا طرح أحد المصادر مشكلة، يمكن للمستخدم إغلاقها على شاشة "مركز الأمان" بالنقر على زر الإغلاق (الزر X على بطاقة التحذير).
- عندما يغلق المستخدم مشكلة، لن تظهر مجددًا في واجهة المستخدم إذا استمرت.
- وتظل عمليات الإغلاق المستمرة على القرص أثناء إعادة تشغيل الجهاز.
- إذا توقّف مصدر "مركز السلامة" عن تقديم مشكلة ثمّ أبلغ عن المشكلة مرة أخرى في وقت لاحق، ستظهر المشكلة مجددًا. يهدف ذلك إلى السماح بتسجيل الحالات التي يرى فيها المستخدم تحذيرًا ويغلقه، ثم يتّخذ إجراءً يُفترض أن يخفّف المشكلة، ولكنّ المستخدم ينفّذ بعد ذلك إجراءً آخر يؤدي مجددًا إلى حدوث مشكلة مشابهة. وفي هذه المرحلة، من المفترض أن تظهر بطاقة التحذير من جديد.
- تظهر بطاقات التحذير الصفراء والحمراء كل 180 يومًا ما لم يُغلِقها المستخدم عدة مرات.
من المفترض ألا يحتاج المصدر إلى المزيد من السلوكيات الإضافية إلا في الحالات التالية:
- يحاول المصدر تنفيذ هذا السلوك بشكل مختلف، على سبيل المثال، عدم إعادة عرض المشكلة مطلقًا.
- يحاول المصدر استخدام هذا كإجراء استدعاء، على سبيل المثال، لتسجيل المعلومات.
تقديم بيانات لعدة مستخدمين/ملفات شخصية
يمكن استخدام SafetyCenterManager
API على مستوى المستخدمين والملفات الشخصية. لمزيد من
المعلومات، يُرجى الاطّلاع على مقالة إنشاء التطبيقات المتوافقة مع ميزة "الوصول المتعدد"
. يرتبط الكائن Context
الذي يوفّر SafetyCenterManager
بالمثيل UserHandle
، لذا يتفاعل مثيل SafetyCenterManager
المعروض مع
مركز الأمان لمثيل UserHandle
هذا. بشكل تلقائي، يرتبط Context
بالمستخدم الجاري، ولكن من الممكن إنشاء مثيل لمستخدم آخر إذا كان التطبيق يحمل إذنَي INTERACT_ACROSS_USERS
وINTERACT_ACROSS_USERS_FULL
. يوضح هذا المثال إجراء مكالمة عبر
المستخدمين/الملفات الشخصية:
Context userContext = context.createContextAsUser(userHandle, 0);
SafetyCenterManager userSafetyCenterManager = userContext.getSystemService(SafetyCenterManager.class);
if (userSafetyCenterManager == null) {
// Should not be null on T.
return;
}
// Calls to userSafetyCenterManager will provide data for the given userHandle
يمكن لكل مستخدم على الجهاز أن يكون لديه عدة ملفات شخصية مُدارة. ويقدم مركز الأمان بيانات مختلفة لكل مستخدم، إلا أنه يدمج بيانات جميع الملفات الشخصية المُدارة والمرتبطة بمستخدم معين.
عند ضبط القيمة profile="all_profiles"
للمصدر في ملف الإعدادات،
يحدث ما يلي:
- يتوفّر إدخال واجهة مستخدم للمستخدم (الملف الشخصي الرئيسي) وجميع الملفات الشخصية المُدارة المرتبطة به (التي تستخدم مثيلات
titleForWork
). يتم إرسال إشارة التحديث أو إعادة الفحص إلى الملف الشخصي الرئيسي وجميع الملفات الشخصية المُدارة المرتبطة. يتم تشغيل جهاز الاستقبال المرتبط لكل ملف شخصي، ويمكنه تقديم البيانات المرتبطة مباشرةً إلى
SafetyCenterManager
بدون الحاجة إلى إجراء مكالمة بين الملفات الشخصية ما لم يكن جهاز الاستقبال أو التطبيق هوsingleUser
.من المتوقّع أن يقدّم المصدر بيانات للمستخدِم وجميع ملفاته التجارية المُدارة. قد تختلف بيانات كل إدخال في واجهة المستخدم بناءً على الملف الشخصي.
الاختبار
يمكنك الوصول إلى ShadowSafetyCenterManager
واستخدامه في اختبار Robolectric.
private static final String MY_SOURCE_ID = "MySourceId";
private final MyClass myClass = …;
private final SafetyCenterManager safetyCenterManager = getApplicationContext().getSystemService(SafetyCenterManager.class);
@Test
public void whenRefreshingData_providesDataToSafetyCenterForMySourceId() {
shadowOf(safetyCenterManager).setSafetyCenterEnabled(true);
setupDataForMyClass(…);
myClass.refreshData();
SafetySourceData expectedSafetySourceData = …;
assertThat(safetyCenterManager.getSafetySourceData(MY_SOURCE_ID)).isEqualTo(expectedSafetySourceData);
SafetyEvent expectedSafetyEvent = …;
assertThat(shadowOf(safetyCenterManager).getLastSafetyEvent(MY_SOURCE_ID)).isEqualTo(expectedSafetyEvent);
}
يمكنك كتابة المزيد من الاختبارات الشاملة (E2E)، ولكن هذا الإجراء خارج نطاق هذا الدليل. لمزيد من المعلومات عن كتابة اختبارات E2E هذه، اطّلِع على اختبارات CTS (CtsSafetyCenterTestCases).
واجهات برمجة التطبيقات (API) التجريبية والداخلية
يتم استخدام واجهات برمجة التطبيقات الداخلية وواجهات برمجة التطبيقات التجريبية للاستخدام الداخلي، لذا لا يتم وصفها بالتفصيل في هذا الدليل. مع ذلك، قد نوسّع نطاق بعض واجهات برمجة التطبيقات الداخلية في المستقبل للسماح للمصنّعين الأصليين للأجهزة بإنشاء واجهة مستخدم خاصة بهم وسنعدّل هذا الدليل لتقديم إرشادات حول كيفية استخدامها.
الأذونات
MANAGE_SAFETY_CENTER
internal|installer|role
- تُستخدَم لواجهات برمجة تطبيقات Safety Center الداخلية.
- لا يتم منحه إلا لـ PermissionController وshell
تطبيق "الإعدادات"
إعادة التوجيه إلى "مركز الأمان"
يتم الوصول إلى "مركز الأمان" تلقائيًا من خلال تطبيق "الإعدادات" من خلال إدخال الأمان والخصوصية الجديد. إذا كنت تستخدم تطبيق "الإعدادات" مختلفًا أو إذا عدّلت تطبيق "الإعدادات"، قد تحتاج إلى تخصيص كيفية الوصول إلى "مركز الأمان".
عند تفعيل "مركز السلامة":
- إنّ إدخال الخصوصية القديم مخفي.
- الرمز المخفي لإدخال الأمان القديم
- تمت إضافة رمز جديد يخص الأمان والخصوصية.
- إعادة توجيه الإدخال الجديد الأمان والخصوصية إلى رمز مركز الأمان
android.settings.PRIVACY_SETTINGS
وandroid.settings.SECURITY_SETTINGS
: تتم إعادة توجيه إجراءات النية لفتح "مركز الأمان" (الرمز: security، privacy)
صفحات الأمان والخصوصية المتقدمة
يحتوي تطبيق "الإعدادات" على إعدادات إضافية ضمن عنوانَي المزيد من إعدادات الأمان والمزيد من إعدادات الخصوصية، وهما متاحان من "مركز الأمان":
رمز الأمان المتقدّم
رمز الخصوصية المتقدّم
اعتبارًا من Android 14، تم دمج صفحتَي إعدادات الأمان المتقدّمة والخصوصية المتقدّمة ضمن صفحة واحدة بعنوان "تعزيز الأمان والخصوصية" تتضمّن إجراء النية
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
مصادر السلامة
يتكامل "مركز الأمان" مع مجموعة محدّدة من مصادر الأمان يوفّرها تطبيق "الإعدادات":
- يتحقّق مصدر أمان شاشة القفل من أنّه تم إعداد شاشة القفل باستخدام رمز مرور (أو طريقة أمان أخرى)، وذلك لضمان الحفاظ على أمان معلومات المستخدم الخاصة من الوصول الخارجي.
- أسطح مصدر أمان للمقاييس الحيوية (مخفية تلقائيًا) يمكن دمجها مع أداة استشعار للوجه أو بصمة الإصبع
يمكن الوصول إلى رمز المصدر لمصادر "مركز الأمان" هذه من خلال Android code search. إذا لم يتم تعديل تطبيق "الإعدادات" (لم يتم إجراء تغييرات على اسم الحزمة أو رمز المصدر أو رمز المصدر الذي يتعامل مع شاشة القفل والسمات الحيوية)، من المفترض أن يعمل هذا الدمج بشكلٍ تلقائي. بخلاف ذلك، قد يلزم إجراء بعض التعديلات مثل تغيير ملف الإعداد لتغيير اسم حزمة تطبيق "الإعدادات" والمصادر التي تتكامل مع "مركز الأمان"، بالإضافة إلى عملية الدمج. لمزيد من المعلومات، يُرجى الاطّلاع على تعديل ملف الضبط وإعدادات الدمج.
لمحة عن PendingIntent
إذا اعتمدت على عملية دمج تطبيق "الإعدادات" الحالية مع "مركز الأمان" في الإصدار 14 من نظام Android أو الإصدارات الأحدث، هذا يعني أنّه تم إصلاح الخطأ الموضّح أدناه. قراءة هذا القسم ليست ضرورية في هذه الحالة.
عند التأكّد من عدم ظهور الخطأ، عليك ضبط قيمة ضبط مورد XML المنطقي في تطبيق "الإعدادات" على config_isSafetyCenterLockScreenPendingIntentFixed
على true
لإيقاف الحل البديل ضمن "مركز الأمان".
حل PendingIntent
تحدث هذه المشكلة بسبب استخدام "الإعدادات" لإضافات مثيل Intent
لتحديد القطعة التي سيتم فتحها. بما أنّ Intent#equals
لا يأخذ في الاعتبار الإضافات الخاصة بمثيل Intent
، يتم اعتبار مثيل PendingIntent
الخاص بأيقونة قائمة التروس ومحاولة التنقّل في
العنصر متساويين وينقلان إلى واجهة المستخدم نفسها (على الرغم من أنّه
من المفترض أن ينقلا إلى واجهة مستخدم مختلفة). تم إصلاح هذه المشكلة في إصدار QPR من خلال
تمييز مثيلات PendingIntent
حسب رمز الطلب. بدلاً من ذلك،
يمكن التمييز بين هذه القيم باستخدام Intent#setId
.
مصادر الأمان الداخلي
بعض مصادر "مركز الأمان" داخلية ويتم تنفيذها في تطبيق النظام PermissionController داخل وحدة PermissionController. وتعمل هذه المصادر مثل مصادر مركز الأمان العادية ولا تتلقى أي معاملة خاصة. يتوفّر رمز هذه المصادر من خلال بحث رمز Android .
وتشمل هذه الإشارات بشكل أساسي إشارات الخصوصية، على سبيل المثال:
- تسهيل الاستخدام
- الإلغاء التلقائي لأذونات التطبيقات غير المستخدَمة
- الوصول إلى الموقع الجغرافي
- برنامج تلقّي الإشعارات الصوتية
- معلومات سياسة العمل