重新導向至安全中心
任何應用程式都能使用
android.content.Intent.ACTION_SAFETY_CENTER
項動作 (字串值
android.intent.action.SAFETY_CENTER
)。
如要開啟安全中心,請在 Activity
例項中撥打電話:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
重新導向至特定問題
您也可以使用特定意圖額外資料,將使用者重新導向至特定 Safety Center 警告資訊卡。這些額外項目並非供第三方使用,因此屬於 SafetyCenterManager
的一部分,而 SafetyCenterManager
是 @SystemApi
的一部分。僅限
系統應用程式可以存取這些額外功能
重新導向特定警告資訊卡的意圖額外項目:
EXTRA_SAFETY_SOURCE_ID
- 字串值:
android.safetycenter.extra.SAFETY_SOURCE_ID
- 字串類型:指定相關聯安全來源的 ID 警告資訊卡
- 必填,問題重新導向才能正常運作
- 字串值:
EXTRA_SAFETY_SOURCE_ISSUE_ID
- 字串值:
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- 字串類型:指定警告資訊卡 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 中,這會顯示為可摺疊的項目)。
您可以使用這個意圖額外資料,將使用者重新導向至特定子頁面:
EXTRA_SAFETY_SOURCES_GROUP_ID
- 字串值:
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- 字串類型:指定
SafetySourcesGroup
的 ID - 必須使用重新導向功能,將重新導向至子頁面才能運作
- 字串值:
您可以在 Activity
例項中使用下列程式碼片段,將 Safety Center 畫面開啟至特定子頁面:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");
startActivity(openSafetyCenterIntent);
使用 Safety Center 來源 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
物件提供給安全中心,代表 UI 項目和問題清單 (警告卡片)。UI 項目和警告資訊卡可以
SafetySourceData
類別中指定的不同嚴重性等級:
SEVERITY_LEVEL_UNSPECIFIED
- 未指定嚴重性
- 顏色:灰色或透明 (視項目的
SafetySourcesGroup
而定) - 用於在 UI 中做為靜態項目或要顯示的動態資料 未指定的項目
- 不得用於警告資訊卡
SEVERITY_LEVEL_INFORMATION
- 基本資訊或小建議
- 顏色:綠色
SEVERITY_LEVEL_RECOMMENDATION
- 建議使用者採取行動,因為這項問題可能會使他們面臨風險
- 顏色:黃色
SEVERITY_LEVEL_CRITICAL_WARNING
- 嚴重警告,使用者必須採取行動,因為此問題存在風險
- 顏色:紅色
SafetySourceData
SafetySourceData
物件由 UI 項目、警告資訊卡和不變量組成。
- 選用的
SafetySourceStatus
例項 (UI 項目) SafetySourceIssue
例項清單 (警告資訊卡)- 選用
Bundle
額外項目 (14 以上版本) - 不變量:
SafetySourceIssue
清單必須含有不重複的問題 識別碼- 如果有
SafetySourceStatus
,SafetySourceIssue
例項不得比SafetySourceStatus
重要 (除非SafetySourceStatus
是SEVERITY_LEVEL_UNSPECIFIED
,在這種情況下允許SEVERITY_LEVEL_INFORMATION
問題)。 - 您必須遵循 API 設定訂定的其他規定。
舉例來說,如果來源僅涉及問題,就不能提供
SafetySourceStatus
執行個體。
SafetySourceStatus
- 必填的
CharSequence
標題 - 必填
CharSequence
摘要 - 必要的嚴重性等級
- 選用的
PendingIntent
例項,用於將使用者重新導向至正確的網頁 (預設會使用設定中的intentAction
,如果有) - 選用的
IconAction
(在項目中顯示為側邊圖示),由下列項目組成:- 必要的圖示類型,必須為以下其中一種類型:
ICON_TYPE_GEAR
:在 UI 項目旁顯示為齒輪ICON_TYPE_INFO
:顯示為 UI 項目旁的資訊圖示
- 需要
PendingIntent
才能將使用者重新導向至其他網頁
- 必要的圖示類型,必須為以下其中一種類型:
- 可選的布林值
enabled
值,可將 UI 項目標示為已停用,因此無法點選 (預設為true
) - 不變:
PendingIntent
執行個體必須開啟Activity
執行個體。- 如果項目已停用,則必須指定為
SEVERITY_LEVEL_UNSPECIFIED
。 - API 設定強制執行的其他規定。
SafetySourceIssue
- 必填的專屬
String
ID - 必填的
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
ID - 必須提供「
CharSequence
」標籤 - 必要
PendingIntent
將使用者重新導向至其他網頁,或直接在 安全中心畫面 - 選填布林值,指定這個問題是否可從以下位置直接解決:
「安全中心」畫面 (預設為
false
) - 選用的
CharSequence
成功訊息,會在使用者直接透過安全中心畫面成功解決問題時顯示
- 必須提供的專屬
- 使用者關閉問題時呼叫的選用
PendingIntent
(預設為不呼叫) - 必填的
String
問題類型 ID。這與這個問題類似 ID,但可以重複,並會用於進行記錄 - 選填的簡化 ID 為
String
,這可允許發布相同的內容 「SafetySourceIssue
」來自不同來源,且只在以下管道顯示一次 假設它們具有相同的deduplicationGroup
(從 Android 開始) 14)。如未指定,系統就不會去除重複的問題 - 出處標題 (選填)
CharSequence
,這是: 警告資訊卡的來源 (從 Android 開始) 14)。如未指定,系統會使用SafetySourcesGroup
的標題 - 選用的問題可行性 (自 Android 14 起),必須為下列其中一種:
ISSUE_ACTIONABILITY_MANUAL
:使用者需要手動解決這個問題。此為預設值。ISSUE_ACTIONABILITY_TIP
:這個問題只是提示,可能不需要任何使用者輸入內容。ISSUE_ACTIONABILITY_AUTOMATIC
:這個問題已採取行動,可能不需要任何使用者輸入內容。
- 選用的通知行為 (自 Android 14 起),必須為下列其中一種:
NOTIFICATION_BEHAVIOR_UNSPECIFIED
:安全中心會決定是否需要為警告資訊卡發出通知。此為預設值。NOTIFICATION_BEHAVIOR_NEVER
:未發布通知。NOTIFICATION_BEHAVIOR_DELAYED
:有一段時間發布通知 。NOTIFICATION_BEHAVIOR_IMMEDIATELY
:通知張貼時間: 瞭解已回報的問題
- 選用
Notification
,可顯示含有警告資訊卡的自訂通知 (自 Android 14 起)。如果沒有指定,Notification
衍生自警告資訊卡。組成元素:- 必填的
CharSequence
標題 - 必填
CharSequence
摘要 - 使用者可對這則通知採取的
Action
元素清單
- 必填的
- 不變:
Action
例項清單必須由具有不重複 ID 的動作組成Action
執行個體清單必須包含一或兩個Action
元素。如果可操作性不是ISSUE_ACTIONABILITY_MANUAL
,則允許Action
為零。- OnDismiss
PendingIntent
不得開啟Activity
例項 - API 設定設下的額外規定
系統會在特定事件發生時將資料提供給 Safety Center,因此必須指定導致來源提供 SafetySourceData
與 SafetyEvent
例項的因素。
SafetyEvent
- 必要類型,必須是下列其中一種:
SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
:來源狀態 已變更。SAFETY_EVENT_TYPE_REFRESH_REQUESTED
:回應重新整理/重新掃描 來自安全中心的信號;使用這個 API 取代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
無法執行這些操作使用這個 API 取代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 Center 資料不會在重新啟動時保留;因此,您可以使用SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
來取得這項資料。
- 重新整理廣播 ID 的選用
String
ID。 - 針對取得的
SafetySourceIssue
執行個體取得的選用String
ID 均已解決。 - 針對要解析的
SafetySourceIssue.Action
例項,提供選用的String
識別碼。 - 不變:
- 如果類型為
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
,則必須提供重新整理廣播 ID - 如果類型為
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
或SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
,則必須提供問題和動作 ID
- 如果類型為
以下範例說明來源可能如何向安全中心提供資料 (在本例中,它會提供包含單一警告卡片的項目):
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);
取得最後提供的資料
對於您的
應用程式。您可以使用這個功能在自己的 UI 中顯示資料,以檢查資料是否
必須先更新才能執行昂貴的作業
將同一個 SafetySourceData
執行個體連結到安全中心,但有一些變更
新的 SafetyEvent
執行個體。這在測試時也相當實用。
使用以下程式碼,取得 Safety Center 收到的最新資料:
SafetySourceData lastDataProvided =
safetyCenterManager.getSafetySourceData("MySourceId");
回報錯誤
如果無法收集 SafetySourceData
資料,可以向安全團隊回報錯誤
Center,負責將項目變更為灰色、清除快取資料,並提供
訊息,例如「無法檢查設定」。如果發生以下情況,您也可以回報錯誤
無法解析 SafetySourceIssue.Action
的執行個體,在這種情況下,
不會清除快取資料,且使用者介面項目不會變更。但訊息
會在系統發生錯誤時向使用者顯示。
您可以使用 SafetySourceErrorDetails
提供錯誤,其組成方式如下:
SafetySourceErrorDetails
:必要SafetyEvent
執行個體:
// An error has occurred in the background, need to clear the Safety Center data to avoid showing data that may not be valid anymore
SafetyEvent safetyEvent = new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
SafetySourceErrorDetails safetySourceErrorDetails = new SafetySourceErrorDetails(safetyEvent);
safetyCenterManager.reportSafetySourceError("MySourceId", safetySourceErrorDetails);
回應重新整理或重新掃描要求
你可以接收安全中心的訊號,以便提供新資料。回應重新整理或重新掃描要求,可確保使用者在開啟安全中心和輕觸掃描按鈕時,能查看目前的狀態。
方法是透過下列動作接收廣播訊息:
ACTION_REFRESH_SAFETY_SOURCES
- 字串值:
android.safetycenter.action.REFRESH_SAFETY_SOURCES
- 當 Safety Center 傳送要求,要求重新整理特定應用程式的安全性來源資料時觸發
- 只有系統可以傳送的受保護意圖
- 以明確意圖的形式傳送至設定檔中的所有安全性來源,且需要
SEND_SAFETY_CENTER_UPDATE
權限
- 字串值:
本次直播還提供以下額外內容:
EXTRA_REFRESH_SAFETY_SOURCE_IDS
- 字串值:
android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
- 字串陣列類型 (
String[]
),代表要重新整理的來源 ID 指定應用程式
- 字串值:
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
- 字串類型,代表要求重新整理作業的專屬 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
例項,使用者可直接從安全中心畫面解決。使用者輕觸動作按鈕
和 SafetySourceIssue.Action
上的 PendingIntent
例項 (由
觸發安全來源,進而在背景解決問題
會在設定完成後通知安全中心。
如要實作解決動作,如果作業預計需要一段時間 (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] 按鈕) 即可。
- 使用者關閉問題後,如果問題持續存在,系統就不會再次在 UI 中顯示該問題。
- 裝置重新啟動時,磁碟上的永久解除會保留。
- 如果安全中心來源無法解決問題,並提供 日後再次發生問題。這麼做是為了讓 使用者看到警示、關閉廣告,之後採取相應行動 應緩解問題,但使用者接著再執行一次 也會導致類似問題發生此時,警告資訊卡片應會再次顯示。
- 除非使用者 已經多次關閉。
除非發生以下情況,否則來源不應要求採取其他行為:
- 來源嘗試以不同方式實作此行為,例如從未 再次找出問題。
- 來源會嘗試將此做為回呼,例如記錄資訊。
提供多個使用者/設定檔的資料
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
例項) 都有 UI 項目。 系統會針對上層發布商簡介和所有相關的受管理商家檔案傳送重新整理或重新掃描訊號。系統會為每個設定檔啟動相關聯的接收器,並可直接將相關聯資料提供給
SafetyCenterManager
,而不必進行跨設定檔呼叫 (除非接收器或應用程式為singleUser
)。來源應會提供使用者及其所有受管理資料 每個 UI 項目的資料可能因設定檔而異。
測試
您可以存取 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) 自行建構 UI,屆時我們會更新本指南,提供相關使用說明。
權限
MANAGE_SAFETY_CENTER
internal|installer|role
- 用於內部 Safety Center API
- 僅授予 PermissionController 和 shell
「設定」應用程式
安全中心重新導向
根據預設,您可以透過「設定」應用程式存取安全中心,並使用新的「安全性與隱私權」項目。如果您使用其他「設定」應用程式,或已修改「設定」應用程式,可能需要自訂存取安全中心的方式。
啟用安全中心後:
- 舊版隱私權項目隱藏代碼
- 舊版「Security」(安全性) 項目隱藏程式碼
- 新增「安全性與隱私權」項目 code
- 新的「安全性和隱私權」項目會重新導向至安全中心code
- 「
android.settings.PRIVACY_SETTINGS
」和「android.settings.SECURITY_SETTINGS
」 意圖動作會重新導向至開啟安全中心 (程式碼: 安全性, 隱私權)
進階安全性和隱私權頁面
「設定」應用程式中的「其他安全性設定」下方提供了其他設定 和其他隱私權設定標題,這些設定位於安全中心:
進階安全碼
進階隱私權程式碼
自 Android 14 起,進階安全性和隱私權設定頁面會合併至單一「其他安全性與隱私權」頁面,並使用意圖動作
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
安全性來源
Safety Center 會整合「設定」應用程式提供的特定安全性來源:
- 螢幕鎖定功能的安全性來源會確認螢幕鎖定已設定 密碼 (或其他安全性),確保使用者的私人資訊 防止外部存取的安全。
- 生物特徵辨識安全來源 (預設為隱藏) 會顯示,以便整合指紋或臉部辨識感應器。
您可以透過 Android 裝置存取這些安全中心來源的原始碼 代碼 搜尋。 如果未修改「設定」應用程式 (未變更套件名稱、原始碼或處理螢幕鎖定和生物特徵辨識的原始碼),則這項整合功能應可立即使用。否則,您可能需要進行一些修改,例如變更設定檔,以變更設定應用程式的套件名稱,以及與安全中心整合的來源,以及整合作業。詳情請參閱「更新設定檔」和整合設定。
關於 PendingIntent
如果您使用 Android 中現有的「設定」應用程式安全中心 14 以上版本修正了下列錯誤。 在此情況下,您不需要閱讀本節所述的內容。
如果確定錯誤不存在,請設定 XML 布林資源
調整設定值
config_isSafetyCenterLockScreenPendingIntentFixed
到true
即可關閉
建議您前往安全中心提供專門的解決方法
PendingIntent 解決方法
這項錯誤是因為設定使用 Intent
例項額外項目來判斷要開啟哪個 Fragment。由於 Intent#equals
不會考量 Intent
例項額外項目,因此齒輪選單圖示和項目的 PendingIntent
例項會視為相同,並導向相同的 UI (即使它們原本要導向不同的 UI)。QPR 版本中已修正這個問題,並已於
依據要求代碼區分 PendingIntent
例項。另外
我們就用 Intent#setId
來區分。
內部安全來源
部分安全中心來源是內部來源,會在 PermissionController 模組中的 PermissionController 系統應用程式中實作。這些 這些來源的行為如同一般安全中心,而且不會與任何 治療方式,這些來源的程式碼可透過 Android 程式碼取得 搜尋。
這些主要是隱私權信號,例如:
- 無障礙設定
- 自動撤銷未使用的應用程式
- 位置資訊存取權
- 通知接聽器
- 工作政策資訊