與安全中心互動

重新導向至安全中心

任何應用程式都能使用 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
    • 字串類型:指定相關聯安全來源的 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 執行個體中使用以下程式碼片段來開啟 進入特定子頁面:

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 Source API
    • 僅限安全來源使用
    • 只能授予已加入許可清單的系統應用程式

這是特殊權限,如要取得這些權限,請將其新增到 相關檔案,例如 com.android.settings.xml敬上 檔案,以及應用程式的 AndroidManifest.xml 檔案。詳情請見 protectionLevel敬上 進一步瞭解權限模型

取得 SafetyCenterManager

SafetyCenterManager@SystemApi 類別,可透過系統應用程式存取 。這場呼叫會示範 取得 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_STATUSSEND_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 清單必須含有不重複的問題 識別碼
    • SafetySourceIssue 執行個體的重要性不得大於 如果有,則輸入 SafetySourceStatus (除非 SafetySourceStatusSEVERITY_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_MANUALAction 的值不得為零
    • OnDismiss PendingIntent 不得開啟 Activity 執行個體
    • API 設定設下的額外規定

我們會在特定事件發生時將相關資料提供給安全中心,因此我們必須 指明導致來源提供 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_EVENT_TYPE_SOURCE_STATE_CHANGED
  • 重新整理廣播 ID 的選用 String ID。
  • 針對取得的 SafetySourceIssue 執行個體取得的選用 String ID 均已解決。
  • SafetySourceIssue.Action 執行個體的選用 String ID 解決問題
  • 不變:
    • 如果類型為 SAFETY_EVENT_TYPE_REFRESH_REQUESTED
    • 如果類型為 SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDEDSAFETY_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);

取得最後提供的資料

對於您的 應用程式。您可以使用這個功能在自己的 UI 中顯示資料,以檢查資料是否 必須先更新才能執行昂貴的作業 將同一個 SafetySourceData 執行個體連結到安全中心,但有一些變更 新的 SafetyEvent 執行個體。也非常適合用於測試。

使用此代碼取得提供給安全中心的最新資料:

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
    • 在安全中心傳送重新整理資料的要求時, 特定應用程式的安全來源
    • 只能由系統傳送的受保護意圖
    • 以明確形式傳送給設定檔中的所有安全來源 意圖並需要 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] 按鈕) 即可。
  • 使用者關閉問題後,如果問題持續發生,則不會再顯示 繼續在使用者介面中顯示
  • 裝置重新啟動時,磁碟上的永久關閉行為仍會保留。
  • 如果安全中心來源無法解決問題,並提供 日後再次發生問題。這麼做是為了讓 使用者看到警示、關閉廣告,之後採取相應行動 應緩解問題,但使用者接著再執行一次 也會導致類似問題發生警告資訊卡應會重新顯示。
  • 除非使用者 已經多次關閉。

除非發生以下情況,否則來源不應要求採取其他行為:

  • 來源嘗試以不同方式實作此行為,例如從未 再次找出問題。
  • 舉例來說,來源會嘗試使用此回呼做為回呼,例如, 可能不準確或不適當

提供多個使用者/設定檔的資料

SafetyCenterManager API 可用於不同的使用者和設定檔。如要 資訊,請參閱「打造多使用者感知能力 應用程式Context 提供 SafetyCenterManager 的物件與 UserHandle 相關聯 例項,因此傳回的 SafetyCenterManager 例項會與 該 UserHandle 執行個體的安全中心。根據預設,Context 為 但可以建立執行個體 如果應用程式擁有 INTERACT_ACROSS_USERSINTERACT_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" 之後, 會發生下列情況:

  • 使用者 (設定檔父項) 和所有相關聯的 UI 項目都有 UI 項目 受管理設定檔 (使用 titleForWork 執行個體)。
  • 系統將為設定檔父項和所有 相關聯的受管理設定檔系統會為每個 並且可直接將相關資料提供給 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) 自行建構使用者介面。我們也會更新本指南, 提供使用指南

權限

  • MANAGE_SAFETY_CENTER
    • internal|installer|role
    • 用於內部安全中心 API
    • 僅授予 PermissionController 和 shell

「設定」應用程式

安全中心重新導向

根據預設,您可以透過「設定」應用程式存取安全中心,以及全新的 安全性和privacy 項目上。如果您使用其他「設定」應用程式 你修改了「設定」應用程式後,可能需要自訂安全中心的方式 加以存取。

啟用安全中心後:

  • 舊版「隱私權」項目已隱藏程式碼
  • 舊版「Security」(安全性) 項目隱藏程式碼
  • 全新安全性與privacy 項目加上 code
  • 全新安全性與privacy 項目重新導向安全中心程式碼
  • android.settings.PRIVACY_SETTINGS」和「android.settings.SECURITY_SETTINGS」 意圖動作會重新導向至開啟安全中心 (程式碼: 安全性隱私權)

進階安全性與隱私權頁面

「設定」應用程式中的「其他安全性設定」下方提供了其他設定 和其他隱私權設定標題,這些設定位於安全中心:

安全性來源

安全中心與 Google 設定應用程式:

  • 螢幕鎖定功能的安全性來源會確認螢幕鎖定已設定 密碼 (或其他安全性),確保使用者的私人資訊 防止外部存取的安全。
  • 要整合的生物特徵辨識安全來源 (預設為隱藏) 介面 指紋或臉部感應器

您可以透過 Android 裝置存取這些安全中心來源的原始碼 代碼 搜尋。 如果「設定」應用程式未修改 (套件名稱不會變動), 原始碼或處理螢幕鎖定和生物特徵辨識的原始碼), 那麼這項整合應該就能立即生效否則,有些修改 例如變更設定檔以變更套件 「設定」應用程式的名稱,以及與安全中心整合的來源, 以及整合功能詳情請參閱「更新設定 檔案整合 設定

關於 PendingIntent

如果您使用 Android 中現有的「設定」應用程式安全中心 14 以上版本修正了下列錯誤。 在此情況下,您不需要閱讀本節所述的內容。

如果確定錯誤不存在,請設定 XML 布林資源 調整設定值 config_isSafetyCenterLockScreenPendingIntentFixedtrue即可關閉 建議您前往安全中心提供專門的解決方法

PendingIntent 解決方法

這項錯誤是因為設定使用 Intent 例項額外項目,判斷哪些 要開啟的片段。因為 Intent#equals 不會取得 Intent 例項 額外功能,則齒輪圖示的 PendingIntent 例項和 系統會將項目視為相等並瀏覽相同的 UI (即使 目的在於前往不同 UIQPR 版本中已修正這個問題,並已於 依據要求代碼區分 PendingIntent 例項。另外 我們就用 Intent#setId 來區分。

內部安全來源

有些安全中心來源屬於內部資料, PermissionController 模組內的 PermissionController 系統應用程式這些 這些來源的行為如同一般安全中心,而且不會與任何 治療方式,這些來源的程式碼可透過 Android 程式碼取得 搜尋

這些主要是隱私權信號,例如:

  • 無障礙設定
  • 自動撤銷未使用的應用程式
  • 位置資訊存取權
  • 通知接聽器
  • 工作政策資訊