הפנה מחדש למרכז הבטיחות
כל אפליקציה יכולה לפתוח את מרכז הבטיחות באמצעות הפעולה android.content.Intent.ACTION_SAFETY_CENTER
(ערך מחרוזת android.intent.action.SAFETY_CENTER
).
כדי לפתוח את מרכז הבטיחות, בצע שיחה מתוך מופע Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
הפנה מחדש לנושא ספציפי
אפשר גם להפנות לכרטיס אזהרה ספציפי של מרכז הבטיחות באמצעות תוספות כוונה ספציפיות. התוספות האלה לא נועדו לשמש צדדים שלישיים ולכן הן חלק מ- SafetyCenterManager
, שהוא חלק מ- @SystemApi
. רק אפליקציות מערכת יכולות לגשת לתוספות האלה.
תוספות כוונות שמפנות מחדש כרטיס אזהרה ספציפי:
-
EXTRA_SAFETY_SOURCE_ID
- ערך מחרוזת:
android.safetycenter.extra.SAFETY_SOURCE_ID
- סוג מחרוזת: מציין את המזהה של מקור הבטיחות של כרטיס האזהרה המשויך
- נדרש כדי שההפניה מחדש לבעיה תעבוד
- ערך מחרוזת:
-
EXTRA_SAFETY_SOURCE_ISSUE_ID
- ערך מחרוזת:
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- סוג מחרוזת: מציין את מזהה כרטיס האזהרה
- נדרש כדי שההפניה מחדש לבעיה תעבוד
- ערך מחרוזת:
-
EXTRA_SAFETY_SOURCE_USER_HANDLE
- ערך מחרוזת:
android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
- סוג
UserHandle
: מציין אתUserHandle
עבור כרטיס האזהרה המשויך - אופציונלי (ברירת המחדל היא המשתמש הנוכחי)
- ערך מחרוזת:
ניתן להשתמש בקטע הקוד שלהלן מתוך מופע Activity
כדי לפתוח את מסך מרכז הבטיחות לבעיה ספציפית:
UserHandle theUserHandleThisIssueCameFrom = …;
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_ID, "TheSafetySourceIdThisIssueCameFrom")
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID, "TheSafetySourceIssueIdToRedirectTo")
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_USER_HANDLE, theUserHandleThisIssueCameFrom);
startActivity(openSafetyCenterIntent);
הפנה מחדש לדף משנה ספציפי (החל מ-Android 14)
באנדרואיד 14 ומעלה, דף מרכז הבטיחות מחולק לדפי משנה מרובים המייצגים את SafetySourcesGroup
השונות (באנדרואיד 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 זמין ב- Code Search .
הרשאות
ממשקי ה-API של המקור של מרכז הבטיחות נגישים רק על ידי אפליקציות מערכת הרשומות ברשימה באמצעות ההרשאות המפורטות למטה. למידע נוסף, ראה רישום הרשאות מורשות .
-
READ_SAFETY_CENTER_STATUS
-
signature|privileged
- משמש עבור ה-API
SafetyCenterManager#isSafetyCenterEnabled()
(לא נחוץ עבור מקורות מרכז הבטיחות, הם זקוקים רק להרשאתSEND_SAFETY_CENTER_UPDATE
) - בשימוש על ידי אפליקציות מערכת שבודקות אם מרכז הבטיחות מופעל
- מוענק רק לאפליקציות מערכת המורשות
-
-
SEND_SAFETY_CENTER_UPDATE
-
internal|privileged
- משמש עבור ה-API המופעל וממשק ה-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
(החל מ-Android 14). אם לא צוין, הבעיה לעולם אינה משוכפלת -
CharSequence
אופציונלי עבור כותרת הייחוס, זהו טקסט שמראה מהיכן מקורו של כרטיס האזהרה (החל באנדרואיד 14). אם לא צוין, משתמש בכותרת שלSafetySourcesGroup
- יכולת פעולה אופציונלית לבעיה (החל מ-Android 14), אשר חייבת להיות אחת מ:
-
ISSUE_ACTIONABILITY_MANUAL
: המשתמש צריך לפתור בעיה זו באופן ידני. זוהי ברירת המחדל. -
ISSUE_ACTIONABILITY_TIP
: בעיה זו היא רק טיפ וייתכן שלא תדרוש קלט משתמש כלשהו. -
ISSUE_ACTIONABILITY_AUTOMATIC
: בעיה זו כבר טופלה וייתכן שלא תדרוש קלט משתמש כלשהו.
-
- אופן הפעולה של התראות אופציונלי (החל מ-Android 14), אשר חייב להיות אחד מה:
-
NOTIFICATION_BEHAVIOR_UNSPECIFIED
: מרכז הבטיחות יחליט אם יש צורך בהודעה עבור כרטיס האזהרה. זוהי ברירת המחדל. -
NOTIFICATION_BEHAVIOR_NEVER
: לא פורסמה התראה. -
NOTIFICATION_BEHAVIOR_DELAYED
: הודעה מתפרסמת זמן מה לאחר הדיווח הראשון על הבעיה. -
NOTIFICATION_BEHAVIOR_IMMEDIATELY
: הודעה מתפרסמת ברגע שהבעיה מדווחת.
-
-
Notification
אופציונלית , כדי להציג הודעה מותאמת אישית עם כרטיס האזהרה (החל מ-Android 14). אם לא צוין,Notification
נגזרת מכרטיס האזהרה. מורכב מ:- כותרת
CharSequence
נדרשת - תקציר
CharSequence
נדרש - רשימת רכיבי
Action
שהמשתמש יכול לבצע עבור הודעה זו
- כותרת
- אינוריאנטים:
- רשימת מופעי
Action
חייבת להיות מורכבת מפעולות עם מזהים ייחודיים - רשימת מופעי
Action
חייבת להכיל רכיבAction
אחד או שניים. אם יכולת הפעולה אינהISSUE_ACTIONABILITY_MANUAL
, מותר להשתמש באפסAction
. - אסור ל-OnDismiss
PendingIntent
לפתוח מופעActivity
- דרישות נוספות המוטלות על ידי תצורת ה-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
).
השתמש בקוד זה כדי לשלוח בעיה לפתור בעיה למרכז הבטיחות:
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 פנימיים בעתיד כדי לאפשר ליצרני OEM לבנות ממנו ממשק משתמש משלהם, ואנו נעדכן את המדריך הזה כדי לספק הנחיות כיצד להשתמש בהם.
הרשאות
-
MANAGE_SAFETY_CENTER
-
internal|installer|role
- משמש עבור ממשקי API של מרכז הבטיחות הפנימיים
- ניתן רק ל- PermissionController ולמעטפת
-
אפליקציית הגדרות
הפנייה מחדש של מרכז הבטיחות
כברירת מחדל, ניתן לגשת למרכז הבטיחות דרך אפליקציית ההגדרות עם ערך אבטחה ופרטיות חדש. אם אתה משתמש באפליקציית הגדרות אחרת או אם שינית את אפליקציית ההגדרות, ייתכן שיהיה עליך להתאים אישית את אופן הגישה למרכז הבטיחות.
כאשר מרכז הבטיחות מופעל:
- הזנת פרטיות מדור קודם היא קוד נסתר
- ערך אבטחה מדור קודם הוא קוד מוסתר
- קוד חדש נוסף בנושא אבטחה ופרטיות
- ערך אבטחה ופרטיות חדש מפנה לקוד של מרכז הבטיחות
- פעולות הכוונה
android.settings.PRIVACY_SETTINGS
ו-android.settings.SECURITY_SETTINGS
מנותבות מחדש לפתיחת מרכז הבטיחות (קוד: אבטחה , פרטיות )
דפי אבטחה ופרטיות מתקדמים
אפליקציית ההגדרות מכילה הגדרות נוספות תחת הגדרות אבטחה נוספות וכותרות הגדרות פרטיות נוספות , הזמינות ממרכז הבטיחות:
קוד אבטחה מתקדם
קוד פרטיות מתקדם
החל מ-Android 14, דף הגדרות האבטחה המתקדמות והפרטיות המתקדמות מתמזגים תחת דף "עוד אבטחה ופרטיות" אחד עם פעולת כוונה
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
מקורות בטיחות
מרכז הבטיחות משתלב עם סט ספציפי של מקורות בטיחות שמסופקים על ידי אפליקציית ההגדרות:
- מקור בטיחות מסך נעילה מוודא שמסך נעילה מוגדר עם קוד סיסמה (או אבטחה אחרת), כדי להבטיח שהמידע הפרטי של המשתמש נשמר מגישה חיצונית.
- מקור בטיחות ביומטרי (מוסתר כברירת מחדל) משטח לשילוב עם טביעת אצבע או חיישן פנים.
קוד המקור של מקורות אלו של מרכז הבטיחות נגיש באמצעות חיפוש קודים של Android . אם אפליקציית ההגדרות לא משתנה (לא בוצעו שינויים בשם החבילה, קוד המקור או קוד המקור העוסק במסך נעילה וביומטריה), אזי האינטגרציה הזו אמורה לפעול מחוץ לקופסה. אחרת, ייתכן שיידרשו שינויים מסוימים, כגון שינוי קובץ התצורה כדי לשנות את שם החבילה של אפליקציית ההגדרות והמקורות המשתלבים עם מרכז הבטיחות, כמו גם האינטגרציה. למידע נוסף, ראה עדכון קובץ התצורה והגדרות האינטגרציה .
על PendingIntent
אם אתה מסתמך על השילוב הקיים של אפליקציית הגדרות מרכז הבטיחות באנדרואיד 14 ומעלה, הבאג המתואר להלן תוקן. קריאת סעיף זה אינה הכרחית במקרה זה.
כאשר אתה בטוח שהבאג לא קיים, הגדר ערך תצורת משאב בוליאני של XML באפליקציית ההגדרות config_isSafetyCenterLockScreenPendingIntentFixed
ל- true
כדי לבטל את הפתרון לעקיפה בתוך מרכז הבטיחות.
פתרון לעקוף כוונות בהמתנה
באג זה נגרם על ידי הגדרות המשתמשות בתוספות של מופע Intent
כדי לקבוע איזה קטע לפתוח. מכיוון ש- Intent#equals
לא לוקח בחשבון את התוספות של מופע Intent
, מופע PendingIntent
עבור סמל תפריט גלגל השיניים והערך נחשבים שווים ומנווטים לאותו ממשק משתמש (למרות שהם נועדו לנווט לממשק משתמש אחר). בעיה זו תוקנה במהדורת QPR על ידי הבחנה בין מופעי PendingIntent
לפי קוד בקשה. לחלופין, ניתן להבדיל זאת באמצעות Intent#setId
.
מקורות בטיחות פנימיים
חלק ממקורות מרכז הבטיחות הם פנימיים ומיושמים באפליקציית המערכת PermissionController בתוך מודול PermissionController. מקורות אלו מתנהגים כמו מקורות רגילים של מרכז הבטיחות ואינם זוכים לטיפול מיוחד. קוד עבור מקורות אלה זמין באמצעות חיפוש קוד אנדרואיד .
אלו הם בעיקר אותות פרטיות, למשל:
- נְגִישׁוּת
- ביטול אוטומטי של אפליקציות שאינן בשימוש
- גישה למיקום
- מאזין התראות
- מידע על מדיניות עבודה