הפניה אוטומטית למרכז הבטיחות
כל אפליקציה יכולה לפתוח את מרכז הבטיחות באמצעות
פעולה אחת (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
: מציין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 זמין בקטע קוד
חיפוש Google.
הרשאות
רק אפליקציות המערכת שברשימת ההיתרים יכולות לגשת לממשקי ה-API של המקור של מרכז הבטיחות באמצעות ההרשאות שמפורטות בהמשך. מידע נוסף זמין במאמר הרשאות גישה יצירת רשימת היתרים של הרשאות.
READ_SAFETY_CENTER_STATUS
signature|privileged
- משמש ל-API של
SafetyCenterManager#isSafetyCenterEnabled()
(לא שנדרשים למקורות במרכז הבטיחות, הם צריכים רק הרשאהSEND_SAFETY_CENTER_UPDATE
) - בשימוש על ידי אפליקציות מערכת שבודקות אם מרכז הבטיחות מופעל
- מוענק רק לאפליקציות מערכת שנמצאות ברשימת ההיתרים
SEND_SAFETY_CENTER_UPDATE
internal|privileged
- משמש עבור ה-API המופעל וה-Security Sources API
- בשימוש במקורות בטיחות בלבד
- מוענק רק לאפליקציות מערכת שנמצאות ברשימת ההיתרים
ההרשאות האלה מוגבלות ואפשר לקבל אותן רק על ידי הוספתן אל
את הקובץ הרלוונטי, כמו
com.android.settings.xml
לקובץ לאפליקציה 'הגדרות' ולקובץ AndroidManifest.xml
של האפליקציה. צפייה
protectionLevel
לקבלת מידע נוסף על מודל ההרשאות.
הורדה של SafetyCenterManager
SafetyCenterManager
היא מחלקה מסוג @SystemApi
שאפשר לגשת אליה מאפליקציות מערכת
החל מ-Android 13. השיחה הזו היא דוגמה
get 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
זהה (בהתחלת Android 14). אם לא צוין אחרת, הבעיה אף פעם בוטל כפילויות 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
- נשלחה כאובייקט Intent מרומז שמחייב את המאפיין
READ_SAFETY_CENTER_STATUS
הרשאה
- ערך מחרוזת:
פעולת Intent הזו מועילה כדי להפעיל או להשבית תכונות שקשורות אל מרכז הבטיחות במכשיר.
יישום פעולות לפתרון בעיות
פעולה לפתרון היא מופע 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 יום, אלא אם המשתמש סגרתם אותן כמה פעמים.
המקור לא אמור להזדקק להתנהגויות נוספות, אלא אם:
- המקור מנסה להטמיע את ההתנהגות הזו באופן שונה. לדוגמה, לפתור את הבעיה מחדש.
- המקור מנסה להשתמש בנתונים האלה בתור קריאה חוזרת, לדוגמה, כדי לרשום את מידע.
מתן נתונים למספר משתמשים/פרופילים
ניתן להשתמש ב-API SafetyCenterManager
בכל המשתמשים והפרופילים. לקבלת מידע נוסף
מידע נוסף זמין במאמר יצירת גרסה מרובת משתמשים (Multi-user-Aware)
אפליקציות. 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 הפנימיים של מרכז הבטיחות
- מוענק רק ל-PermissionsController ולמעטפת
אפליקציית ההגדרות
הפניה אוטומטית למרכז הבטיחות
כברירת מחדל, ניתן לגשת למרכז הבטיחות דרך אפליקציית ההגדרות, אבטחה פרטיות. אם אתם משתמשים באפליקציית 'הגדרות' אחרת או אם שינית את אפליקציית ההגדרות, יכול להיות שעליך להתאים אישית את האופן שבו מרכז הבטיחות מתבצעת גישה.
כשמרכז הבטיחות מופעל:
- הערך הישן של Privacy (פרטיות) מוסתר בקוד
- רשומת אבטחה מדור קודם מוסתרת על ידי קוד
- תכונות חדשות אבטחה פרטיות נוספה רשומה קוד
- תכונות חדשות אבטחה הערך 'פרטיות' מפנה אוטומטית לקוד של מרכז הבטיחות.
android.settings.PRIVACY_SETTINGS
ו-android.settings.SECURITY_SETTINGS
הפעולות של Intent מופנות לפתיחת מרכז הבטיחות (קוד: אבטחה, פרטיות)
דפים מתקדמים של אבטחה ופרטיות
אפליקציית ההגדרות כוללת הגדרות נוספות בקטע הגדרות אבטחה נוספות וכותרים של הגדרות פרטיות נוספות, שזמינים במרכז הבטיחות:
קוד אבטחה מתקדם
קוד פרטיות מתקדם
החל מ-Android 14, תכונות האבטחה המתקדמות הדף 'הגדרות פרטיות מתקדמות' ממוזג תחת האפשרות 'More Security & פרטיות" דף עם פעולת Intent
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
מקורות בטיחות
מרכז הבטיחות משתלב עם קבוצה ספציפית של מקורות בטיחות שמסופקים על ידי אפליקציית ההגדרות:
- מקור הבטיחות של מסך הנעילה מאמת שהוגדר מסך נעילה עם קוד סיסמה (או אמצעי אבטחה אחר), כדי להבטיח שהמידע הפרטי של המשתמש צריך להיות מוגן מפני גישה חיצונית.
- פלטפורמות של מקור אבטחה ביומטרי (מוסתרת כברירת מחדל) לשילוב עם חיישן טביעות אצבע או חיישן פנים.
אפשר לגשת לקוד המקור של המקורות האלה במרכז הבטיחות באמצעות Android קוד חיפוש. אם אפליקציית ההגדרות לא שונתה (לא מתבצעים שינויים בשם החבילה, קוד מקור או קוד מקור שעוסקים במסך נעילה ובמידע ביומטרי), השילוב הזה אמור לפעול מחוץ לקופסה. אחרת, ייתכן שיהיו שינויים מסוימים ייתכן שיהיה צורך לשנות את הקובץ, כמו שינוי קובץ התצורה כדי לשנות את החבילה. השם של אפליקציית ההגדרות והמקורות שמשתלבים עם מרכז הבטיחות, כמו וגם לשילוב. מידע נוסף זמין במאמר עדכון ההגדרות האישיות של הקובץ וגם שילוב הגדרות.
מידע על PendingIntent
אם אתם מסתמכים על השילוב הקיים של מרכז הבטיחות של אפליקציית ההגדרות ב-Android בגרסה 14 ואילך, הבאג שמתואר בהמשך תוקן. במקרה הזה אין צורך לקרוא את הקטע הזה.
אם בטוחים שהבאג לא קיים, מגדירים משאב בוליאני של XML
ערך הגדרה באפליקציית ההגדרות
config_isSafetyCenterLockScreenPendingIntentFixed
אל true
כדי להשבית את
דרך לעקוף את הבעיה במרכז הבטיחות.
פתרון עקיף של PendingIntent
הבאג הזה נגרם על ידי 'הגדרות' באמצעות תוספות של מופע Intent
כדי לקבוע
מקטע לפתיחה. כי Intent#equals
לא לוקח את המופע Intent
את התוספות הבאות בחשבון, המופע PendingIntent
של הסמל של תפריט גלגל השיניים
נחשבים שוויוניים ומנווטים לאותו ממשק משתמש (למרות שהם
שרוצים לעבור לממשק משתמש אחר). הבעיה הזו תוקנה במהדורה QPR של
הבחנה בין המופעים של PendingIntent
לפי קוד בקשה. לחלופין,
כדי להבחין ביניהם, אפשר להשתמש בפונקציה Intent#setId
.
מקורות בטיחות פנימיים
חלק מהמקורות של מרכז הבטיחות הם פנימיים ומוטמעים אפליקציית המערכת PermissionsController במודול PermissionsController. האלה מקורות פועלים כמו מקורות רגילים של מרכז הבטיחות ולא מקבלים לטיפול. הקוד למקורות האלה זמין באמצעות קוד Android חיפוש.
אלה בעיקר אותות בנושא פרטיות, לדוגמה:
- נגישות
- ביטול אוטומטי של אפליקציות שלא בשימוש
- גישה למיקום
- מאזין להתראות
- פרטים על המדיניות של מקום העבודה