הפניה אוטומטית למרכז הבטיחות
כל אפליקציה יכולה לפתוח את מרכז הבטיחות באמצעות הפעולה 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
type: מציין את הערך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)
ב-Android 14 ואילך, דף מרכז הבטיחות מחולק לכמה דפי משנה שמייצגים את הSafetySourcesGroup
השונים (ב-Android 13, הם מוצגים כרשאות שניתן לכווץ).
אפשר להפנות לדף משנה ספציפי באמצעות האפשרות הנוספת הזו של כוונת הרכישה:
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);
שימוש בממשקי ה-API של מקור הנתונים של מרכז הבטיחות
ממשקי ה-API של מקור מרכז הבטיחות זמינים באמצעות SafetyCenterManager
(שנמצא ב-@SystemApi
). הקוד של ממשק ה-API זמין ב-Code Search.
קוד ההטמעה של ממשקי ה-API זמין בחיפוש קוד.
הרשאות
רק לאפליקציות מערכת שמופיעות ברשימת ההיתרים יש גישה לממשקי ה-API של מקור מרכז הבטיחות, באמצעות ההרשאות שמפורטות בהמשך. מידע נוסף זמין במאמר הוספת הרשאות להרשאה.
READ_SAFETY_CENTER_STATUS
signature|privileged
- משמשת ל-
SafetyCenterManager#isSafetyCenterEnabled()
API (לא נדרשת למקורות של מרכז הבטיחות, הם זקוקים רק להרשאהSEND_SAFETY_CENTER_UPDATE
) - אפליקציות מערכת שמבדקות אם מרכז הבטיחות מופעל משתמשות בה
- הרשאה שמוענקת רק לאפליקציות מערכת שברשימת ההיתרים
SEND_SAFETY_CENTER_UPDATE
internal|privileged
- משמש לממשק ה-API המופעל ול-Safety Sources API
- נעשה שימוש בהם רק על ידי מקורות בטיחות
- הרשאה שמוענקת רק לאפליקציות מערכת שברשימת ההיתרים
ההרשאות האלה הן הרשאות ברמה גבוהה, וניתן לקבל אותן רק על ידי הוספה שלהן לקובץ הרלוונטי, למשל הקובץ com.android.settings.xml
של אפליקציית ההגדרות, ולקובץ AndroidManifest.xml
של האפליקציה. מידע נוסף על מודל ההרשאות זמין במאמר protectionLevel
.
אחזור של SafetyCenterManager
SafetyCenterManager
היא סוג של @SystemApi
שאפשר לגשת אליו מאפליקציות מערכת החל מגרסה 13 של Android. הקריאה הזו מראה איך לקבל את 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
). - צריך לעמוד בדרישות נוספות שהגדרת ה-API מטילה. לדוגמה, אם המקור הוא לבעיות בלבד, אסור לספק מופע של
SafetySourceStatus
.
- רשימת
SafetySourceStatus
- כותרת
CharSequence
חובה - סיכום נדרש של
CharSequence
- רמת החומרה הנדרשת
- מופע אופציונלי של
PendingIntent
להפניית המשתמש לדף הנכון (ברירת המחדל משתמשת ב-intentAction
מהתצורה, אם יש כזה) IconAction
אופציונלי (מוצג כסמל צדדי ברשומה) שמורכב מ:- סוג הסמל הנדרש, שצריך להיות אחד מהסוגים הבאים:
ICON_TYPE_GEAR
: מוצגת כגלגלת לצד הרשומה של ממשק המשתמשICON_TYPE_INFO
: מוצג כסמל מידע לצד הרשומה בממשק המשתמש
- נדרש
PendingIntent
כדי להפנות את המשתמש לדף אחר
- סוג הסמל הנדרש, שצריך להיות אחד מהסוגים הבאים:
- ערך בוליאני
enabled
אופציונלי שמאפשר לסמן את הערך בממשק המשתמש כמושבת, כך שלא ניתן ללחוץ עליו (ברירת המחדל היאtrue
) - תנאים ללא שינוי:
- מכונות
PendingIntent
חייבות לפתוח מכונה שלActivity
. - אם הרשומה מושבתת, צריך לסמן אותה בתור
SEVERITY_LEVEL_UNSPECIFIED
. - דרישות נוספות שמוטלות על ידי הגדרת ה-API.
- מכונות
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
(החל מגרסה 14 של Android). אם לא יצוין, הבעיה לא תבוטל לעולםCharSequence
אופציונלי עבור שם השיוך. זהו טקסט שמציין את המקור של כרטיס האזהרה (החל מ-Android 14). אם לא צוין, המערכת תשתמש בכותרת שלSafetySourcesGroup
- אפשרות לטיפול בבעיה (החל מגרסה 14 של Android), חייבת להיות אחת מהאפשרויות הבאות:
ISSUE_ACTIONABILITY_MANUAL
: המשתמש צריך לפתור את הבעיה הזו באופן ידני. זוהי ברירת המחדל.ISSUE_ACTIONABILITY_TIP
: הבעיה הזו היא רק טיפ, ויכול להיות שלא תידרש קלט מהמשתמש.ISSUE_ACTIONABILITY_AUTOMATIC
: הבעיה כבר טופלה, ויכול להיות שלא תידרש קלט מהמשתמש.
- אופן ההצגה של ההתראות (החל מגרסה 14 של Android), חייב להיות אחד מהאפשרויות הבאות:
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
- דרישות נוספות שמוטלות על ידי הגדרת ה-API
- רשימת המופעים של
הנתונים מסופקים למרכז הבטיחות במקרים מסוימים, לכן צריך לציין מה גרם למקור לספק ל-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
, אתם יכולים לדווח על השגיאה למרכז הבטיחות. המערכת תשנה את הכיתוב של הרשומה לאפור, תנקה את הנתונים ששמורים במטמון ותציג הודעה כמו לא ניתן לבדוק את ההגדרה. אפשר גם לדווח על שגיאה אם מכונה של 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
).
אפשר להשתמש בקוד הזה כדי לשלוח ל-Safety Center דיווח על בעיה שהושלמה:
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 יום, אלא אם המשתמש סגר אותם כמה פעמים.
המקור לא אמור להזדקק להתנהגויות נוספות, אלא אם:
- המקור מנסה להטמיע את ההתנהגות הזו בצורה שונה, למשל, לעולם לא להציג שוב את הבעיה.
- המקור מנסה להשתמש בזה כקריאה חוזרת (callback), למשל כדי לתעד את המידע ביומן.
איך מספקים נתונים לכמה משתמשים/פרופילים
אפשר להשתמש ב-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), אבל זה לא נכלל בהיקף המדריך הזה. מידע נוסף על כתיבת הבדיקות האלה מקצה לקצה זמין במאמר בדיקות CTS (CtsSafetyCenterTestCases)
ממשקי API לבדיקה ולשימוש פנימי
ממשקי ה-API הפנימיים וממשקי ה-API לבדיקה מיועדים לשימוש פנימי, ולכן הם לא מתוארים בפירוט במדריך הזה. עם זאת, יכול להיות שנרחיב בעתיד חלק מממשקי ה-API הפנימיים כדי לאפשר ליצרני ציוד מקורי ליצור ממשק משתמש משלהם, ונתעדכן את המדריך הזה כדי לספק הנחיות לשימוש בהם.
הרשאות
MANAGE_SAFETY_CENTER
internal|installer|role
- משמש לממשקי ה-API הפנימיים של מרכז הבטיחות
- הרשאה שמוענקת רק ל-PermissionController ולמעטפת
אפליקציית ההגדרות
הפניה אוטומטית למרכז הבטיחות
כברירת מחדל, אפשר לגשת למרכז הבטיחות דרך אפליקציית ההגדרות, דרך האפשרות החדשה אבטחה ופרטיות. אם אתם משתמשים באפליקציית הגדרות אחרת או אם שיניתם את אפליקציית ההגדרות, יכול להיות שתצטרכו להתאים אישית את הגישה למרכז הבטיחות.
כשמפעילים את מרכז הבטיחות:
- קוד של רשומה קודמת בנושא פרטיות שמוסתר
- הרשאה קודמת של אבטחה היא קוד מוסתר
- נוספה רשומה חדשה בנושא אבטחה ופרטיות code
- הוספת האפשרות אבטחה ופרטיות שתעביר אוטומטית לדף קוד של מרכז הבטיחות
- פעולות הכוונה
android.settings.PRIVACY_SETTINGS
ו-android.settings.SECURITY_SETTINGS
מנותבות לפתוח את מרכז הבטיחות (קוד: security, privacy)
דפי אבטחה ופרטיות מתקדמים
באפליקציית ההגדרות יש הגדרות נוספות בקטע עוד הגדרות אבטחה ובקטע עוד הגדרות פרטיות, שזמינות דרך מרכז הבטיחות:
קוד אבטחה מתקדם
קוד פרטיות מתקדם
החל מ-Android 14, דף ההגדרות המתקדמות של האבטחה והפרטיות מוזג לדף אחד בשם 'עוד אבטחה ופרטיות' עם פעולת כוונה (intent)
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
מקורות מידע בנושא בטיחות
מרכז הבטיחות משולב עם קבוצה ספציפית של מקורות מידע בנושא בטיחות שמספקת אפליקציית ההגדרות:
- מקור אבטחה של מסך נעילה מאמת שמסך הנעילה מוגדר עם סיסמה (או אמצעי אבטחה אחר), כדי לוודא שהמידע הפרטי של המשתמש מוגן מפני גישה חיצונית.
- מקור בטיחות ביומטרי (מוסתר כברירת מחדל) מופיע כדי לשלב עם חיישן טביעת אצבע או חיישן זיהוי פנים.
אפשר לגשת לקוד המקור של המקורות האלה במרכז הבטיחות דרך Android code search. אם לא משנים את אפליקציית ההגדרות (לא מבצעים שינויים בשם החבילה, בקוד המקור או בקוד המקור שמיועד למסך הנעילה ולביומטריה), השילוב הזה אמור לפעול באופן מיידי. אחרת, יכול להיות שיהיה צורך לבצע שינויים מסוימים, כמו שינוי קובץ התצורה כדי לשנות את שם החבילה של אפליקציית ההגדרות ואת המקורות שמשולבים עם מרכז הבטיחות, וגם את השילוב עצמו. מידע נוסף זמין במאמרים עדכון קובץ התצורה והגדרות השילוב.
מידע על PendingIntent
אם אתם מסתמכים על השילוב הקיים של מרכז הבטיחות באפליקציית ההגדרות ב-Android 14 ואילך, הבאג שמתואר בהמשך תוקן. במקרה כזה, אין צורך לקרוא את הקטע הזה.
כשתהיו בטוחים שהבאג לא קיים, תוכלו להגדיר ערך של הגדרת משאב בוליאני ב-XML באפליקציית ההגדרות config_isSafetyCenterLockScreenPendingIntentFixed
לערך true
כדי להשבית את הפתרון החלופי במרכז הבטיחות.
פתרון עקיף ל-PendingIntent
הבאג הזה נגרם בגלל שההגדרות משתמשות ב-extras של המכונה Intent
כדי לקבוע איזה קטע לפתוח. מכיוון ש-Intent#equals
לא מביאה בחשבון את התוספות של המכונה Intent
, המכונה PendingIntent
של סמל תפריט גלגל השיניים והרשומה נחשבות שוות ומנווטות לאותו ממשק משתמש (למרות שהן אמורות לנווט לממשק משתמש אחר). הבעיה הזו תוקנה במהדורת QPR, על ידי הבחנה בין המכונות של PendingIntent
לפי קוד הבקשה. לחלופין, אפשר להשתמש ב-Intent#setId
כדי להבדיל בין הערכים.
מקורות בטיחות פנימיים
חלק מהמקורות של מרכז הבטיחות הם פנימיים, והם מוטמעים באפליקציית המערכת PermissionController בתוך המודול PermissionController. המקורות האלה מתנהגים כמו מקורות רגילים במרכז הבטיחות, ולא מקבלים טיפול מיוחד. הקוד של המקורות האלה זמין דרך חיפוש הקוד של Android.
אלה בעיקר אותות פרטיות, למשל:
- נגישות
- ביטול אוטומטי של הרשאות לאפליקציות שלא בשימוש
- גישה למיקום
- מאזין להתראות
- פרטים על המדיניות של מקום העבודה