הפניה אוטומטית למרכז הבטיחות
כל אפליקציה יכולה לפתוח את מרכז הבטיחות באמצעות
פעולה אחת (android.content.Intent.ACTION_SAFETY_CENTER
) (ערך מחרוזת
android.intent.action.SAFETY_CENTER
).
כדי לפתוח את מרכז הבטיחות, צריך לבצע שיחה מתוך מופע של Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
הפניה אוטומטית לבעיה ספציפית
אפשר גם להפנות לכרטיס אזהרה ספציפי של מרכז הבטיחות באמצעות תוספי כוונה ספציפיים. התוספים האלה לא מיועדים לשימוש על ידי צדדים שלישיים, ולכן הם חלק מ-SafetyCenterManager
, שהוא חלק מ-@SystemApi
. רק
לאפליקציות מערכת יש גישה לתוספות האלה.
תוספות Intent שמפנות כרטיס אזהרה ספציפי:
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, הערך הזה מוצג כרשומות ניתנות לכיווץ).
אפשר להפנות לדף משנה ספציפי באמצעות תוספת Intent נוספת:
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 זמין ב-חיפוש קוד.
קוד ההטמעה של ממשקי ה-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
שאפשר לגשת אליו מאפליקציות מערכת החל מגרסה 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
). - הדרישות הנוספות שההגדרות האישיות של ה-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
(החל מ-Android 14): הבעיה משפיעה על הנתונים של המשתמש.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
- יכולת פעולה אופציונלית של הבעיה (החל מ-Android 14),
שחייב להיות אחד מאלה:
ISSUE_ACTIONABILITY_MANUAL
: המשתמש צריך לפתור את הבעיה במצב ה-GRU (זוהי ברירת המחדל)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
- דרישות נוספות שקבעו הגדרות ה-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
- מופעל כשנשלחת בקשה ממרכז הבטיחות לרענון הנתונים של מקור הבטיחות של אפליקציה מסוימת
- כוונה מוגנת שניתן לשלוח רק באמצעות המערכת
- נשלח לכל מקורות הבטיחות בקובץ התצורה באמצעות
Intent ונדרשת ההרשאה
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"
בקובץ התצורה
חייבים להגדיר כדי שהמקור יקבל את השידור שמועבר במקרים האלה.
תגובה למרכז הבטיחות כשהוא מופעל או מושבת
אפשר להגיב כאשר מרכז הבטיחות מופעל או מושבת באמצעות פעולת Intent:
ACTION_SAFETY_CENTER_ENABLED_CHANGED
- ערך מחרוזת:
android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
- מופעל כשמרכז הבטיחות מופעל או מושבת בזמן שהמכשיר פועל
- לא נקראת במהלך האתחול (לשם כך משתמשים ב-
ACTION_BOOT_COMPLETED
). - כוונה מוגנת שניתן לשלוח רק באמצעות המערכת
- נשלח לכל מקורות הבטיחות בקובץ התצורה באמצעות
Intent, נדרשת ההרשאה
SEND_SAFETY_CENTER_UPDATE
- נשלחת ככוונה משתמעת שדורשת את ההרשאה
READ_SAFETY_CENTER_STATUS
- ערך מחרוזת:
פעולת Intent הזו מועילה כדי להפעיל או להשבית תכונות שקשורות אל מרכז הבטיחות במכשיר.
הטמעת פעולות פתרון
פעולה לפתרון היא מופע 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 יום, אלא אם המשתמש סגר אותם כמה פעמים.
המקור לא אמור להזדקק להתנהגויות נוספות, אלא אם:
- המקור מנסה להטמיע את ההתנהגות הזו בצורה שונה, למשל, לא להציג שוב את הבעיה.
- המקור מנסה להשתמש בנתונים האלה בתור קריאה חוזרת, לדוגמה, כדי לרשום את מידע.
איך מספקים נתונים לכמה משתמשים/פרופילים
ניתן להשתמש ב-API SafetyCenterManager
בכל המשתמשים והפרופילים. למידע נוסף, ראו פיתוח אפליקציות שמזהות משתמשים מרובים. האובייקט 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 לבדיקה ופנימיים
ממשקי ה-API הפנימיים וממשקי ה-API לבדיקה מיועדים לשימוש פנימי, ולכן הם לא מתוארים בפירוט במדריך הזה. עם זאת, יכול להיות שנרחיב בעתיד חלק מממשקי ה-API הפנימיים כדי לאפשר ליצרני ציוד מקורי ליצור ממשק משתמש משלהם, ונעדכן את המדריך הזה כדי לספק הנחיות לשימוש בהם.
הרשאות
MANAGE_SAFETY_CENTER
internal|installer|role
- משמש לממשקי ה-API הפנימיים של מרכז הבטיחות
- הרשאה שמוענקת רק ל-PermissionController ולמעטפת
אפליקציית ההגדרות
הפניה אוטומטית למרכז הבטיחות
כברירת מחדל, אפשר לגשת למרכז הבטיחות דרך אפליקציית ההגדרות, בקטע החדש אבטחה ופרטיות. אם אתם משתמשים באפליקציית 'הגדרות' אחרת או אם שינית את אפליקציית ההגדרות, יכול להיות שעליך להתאים אישית את האופן שבו מרכז הבטיחות מתבצעת גישה.
כשמרכז הבטיחות מופעל:
- קוד של רשומת פרטיות מדור קודם שמוסתר
- הרשאה קודמת של אבטחה היא קוד מוסתר
- תכונות חדשות אבטחה פרטיות נוספה רשומה קוד
- תכונות חדשות אבטחה הערך 'פרטיות' מפנה אוטומטית לקוד של מרכז הבטיחות.
- פעולות הכוונה
android.settings.PRIVACY_SETTINGS
ו-android.settings.SECURITY_SETTINGS
מועברות לכתובת אחרת כדי לפתוח את מרכז הבטיחות (קוד: security, privacy)
דפים מתקדמים של אבטחה ופרטיות
אפליקציית ההגדרות כוללת הגדרות נוספות בקטע הגדרות אבטחה נוספות וכותרים של הגדרות פרטיות נוספות, שזמינים במרכז הבטיחות:
קוד אבטחה מתקדם
קוד פרטיות מתקדם
החל מ-Android 14, דף ההגדרות המתקדמות של האבטחה והפרטיות מוזג לדף אחד בשם 'עוד אבטחה ופרטיות' עם פעולת כוונה (intent)
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
מקורות בטיחות
מרכז הבטיחות משתלב עם קבוצה ספציפית של מקורות בטיחות שמסופקים על ידי אפליקציית ההגדרות:
- מקור הבטיחות של מסך הנעילה מאמת שהוגדר מסך נעילה עם קוד סיסמה (או אמצעי אבטחה אחר), כדי להבטיח שהמידע הפרטי של המשתמש צריך להיות מוגן מפני גישה חיצונית.
- פלטפורמות של מקור אבטחה ביומטרי (מוסתרת כברירת מחדל) לשילוב עם חיישן טביעות אצבע או חיישן פנים.
אפשר לגשת לקוד המקור של המקורות האלה במרכז הבטיחות דרך Android קוד חיפוש. אם אפליקציית ההגדרות לא שונתה (לא מתבצעים שינויים בשם החבילה, קוד מקור או קוד מקור שעוסקים במסך נעילה ובמידע ביומטרי), השילוב הזה אמור לפעול מחוץ לקופסה. אחרת, יכול להיות שתצטרכו לבצע שינויים מסוימים, כמו שינוי קובץ התצורה כדי לשנות את שם החבילה של אפליקציית ההגדרות ואת המקורות שמשולבים עם מרכז הבטיחות, וגם את השילוב עצמו. מידע נוסף זמין במאמר עדכון ההגדרות האישיות של הקובץ וגם שילוב הגדרות.
מידע על PendingIntent
אם אתם מסתמכים על השילוב הקיים של מרכז הבטיחות באפליקציית ההגדרות ב-Android מגרסה 14 ואילך, הבאג שמתואר בהמשך תוקן. במקרה הזה אין צורך לקרוא את הקטע הזה.
אם בטוחים שהבאג לא קיים, מגדירים משאב בוליאני של XML
ערך הגדרה באפליקציית ההגדרות
config_isSafetyCenterLockScreenPendingIntentFixed
אל true
כדי להשבית את
דרך לעקוף את הבעיה במרכז הבטיחות.
פתרון עקיף של PendingIntent
הבאג הזה נגרם בגלל שההגדרות משתמשות ב-extras של המכונה Intent
כדי לקבוע איזה קטע לפתוח. כי Intent#equals
לא לוקח את המופע Intent
את התוספות הבאות בחשבון, המופע PendingIntent
של הסמל של תפריט גלגל השיניים
נחשבים שוויוניים ומנווטים לאותו ממשק משתמש (למרות שהם
שרוצים לעבור לממשק משתמש אחר). הבעיה הזו תוקנה במהדורת QPR, על ידי הבחנה בין המכונות של PendingIntent
לפי קוד הבקשה. לחלופין,
כדי להבחין ביניהם, אפשר להשתמש בפונקציה Intent#setId
.
מקורות בטיחות פנימיים
חלק מהמקורות של מרכז הבטיחות הם פנימיים, והם מיושמים באפליקציית המערכת PermissionController בתוך המודול PermissionController. האלה מקורות פועלים כמו מקורות רגילים של מרכז הבטיחות ולא מקבלים לטיפול. הקוד של המקורות האלה זמין דרך חיפוש קוד ב-Android.
אלה בעיקר אותות בנושא פרטיות, לדוגמה:
- נגישות
- ביטול אוטומטי של הרשאות לאפליקציות שלא בשימוש
- גישה למיקום
- מאזין להתראות
- פרטים על המדיניות של מקום העבודה