Tương tác với Trung tâm an toàn

Chuyển hướng đến Trung tâm An toàn

Bất kỳ ứng dụng nào cũng có thể mở Trung tâm an toàn bằng hành động android.content.Intent.ACTION_SAFETY_CENTER (giá trị chuỗi android.intent.action.SAFETY_CENTER ).

Để mở Trung tâm an toàn, hãy thực hiện cuộc gọi từ trong phiên bản Activity :

Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);

startActivity(openSafetyCenterIntent);

Chuyển hướng đến một vấn đề cụ thể

Bạn cũng có thể chuyển hướng đến thẻ cảnh báo của Trung tâm An toàn cụ thể bằng cách sử dụng các tính năng bổ sung có mục đích cụ thể. Các tính năng bổ sung này không dành cho các bên thứ ba sử dụng nên chúng là một phần của SafetyCenterManager , một phần của @SystemApi . Chỉ các ứng dụng hệ thống mới có thể truy cập các tính năng bổ sung này.

Các tính năng bổ sung có ý định chuyển hướng một thẻ cảnh báo cụ thể:

  • EXTRA_SAFETY_SOURCE_ID
    • Giá trị chuỗi: android.safetycenter.extra.SAFETY_SOURCE_ID
    • Loại chuỗi: Chỉ định ID nguồn an toàn của thẻ cảnh báo liên quan
    • Cần thiết để chuyển hướng đến vấn đề hoạt động
  • EXTRA_SAFETY_SOURCE_ISSUE_ID
    • Giá trị chuỗi: android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
    • Loại chuỗi: Chỉ định ID thẻ cảnh báo
    • Cần thiết để chuyển hướng đến vấn đề hoạt động
  • EXTRA_SAFETY_SOURCE_USER_HANDLE
    • Giá trị chuỗi: android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
    • Loại UserHandle : Chỉ định UserHandle cho thẻ cảnh báo liên quan
    • Tùy chọn (mặc định là người dùng hiện tại)

Đoạn mã bên dưới có thể được sử dụng từ trong phiên bản Activity để mở màn hình Trung tâm an toàn cho một vấn đề cụ thể:

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);

Chuyển hướng đến một trang con cụ thể (Bắt đầu từ Android 14)

Trong Android 14 trở lên, trang Trung tâm an toàn được chia thành nhiều trang con đại diện cho SafetySourcesGroup khác nhau (trong Android 13, trang này được hiển thị dưới dạng các mục có thể thu gọn).

Có thể chuyển hướng đến một trang con cụ thể bằng cách sử dụng thêm mục đích này:

  • EXTRA_SAFETY_SOURCES_GROUP_ID
    • Giá trị chuỗi: android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
    • Loại chuỗi: Chỉ định ID của SafetySourcesGroup
    • Cần thiết để chuyển hướng đến trang con hoạt động

Đoạn mã bên dưới có thể được sử dụng từ trong phiên bản Activity để mở màn hình Trung tâm an toàn tới một trang con cụ thể:

Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");

startActivity(openSafetyCenterIntent);

Sử dụng API nguồn của Trung tâm an toàn

API nguồn của Trung tâm an toàn có sẵn bằng cách sử dụng SafetyCenterManager (là @SystemApi ). Mã cho bề mặt API có sẵn trong Tìm kiếm mã . Mã triển khai của API có sẵn trong Code Search .

Quyền

Chỉ những ứng dụng hệ thống có trong danh sách cho phép mới có thể truy cập được API nguồn của Trung tâm an toàn bằng các quyền được liệt kê bên dưới. Để biết thêm thông tin, hãy xem Danh sách cho phép cấp phép đặc quyền .

  • READ_SAFETY_CENTER_STATUS
    • signature|privileged
    • Được sử dụng cho API SafetyCenterManager#isSafetyCenterEnabled() (không cần thiết cho các nguồn của Trung tâm an toàn, chúng chỉ cần quyền SEND_SAFETY_CENTER_UPDATE )
    • Được sử dụng bởi các ứng dụng hệ thống để kiểm tra xem Trung tâm an toàn có được bật hay không
    • Chỉ cấp cho các ứng dụng hệ thống có trong danh sách cho phép
  • SEND_SAFETY_CENTER_UPDATE
    • internal|privileged
    • Được sử dụng cho API đã bật và API nguồn an toàn
    • Chỉ được sử dụng bởi các nguồn an toàn
    • Chỉ cấp cho các ứng dụng hệ thống có trong danh sách cho phép

Các quyền này là đặc quyền và bạn chỉ có thể có được chúng bằng cách thêm chúng vào tệp có liên quan, ví dụ: tệp com.android.settings.xml cho ứng dụng Cài đặt và vào tệp AndroidManifest.xml của ứng dụng. Xem protectionLevel để biết thêm thông tin về mô hình cấp phép.

Tải Trình quản lý Trung tâm An toàn

SafetyCenterManager là một lớp @SystemApi có thể truy cập được từ các ứng dụng hệ thống bắt đầu từ Android 13. Lệnh gọi này minh họa cách tải 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;
}

Kiểm tra xem Trung tâm an toàn có được bật không

Cuộc gọi này sẽ kiểm tra xem Trung tâm an toàn có được bật hay không. Cuộc gọi yêu cầu quyền READ_SAFETY_CENTER_STATUS hoặc quyền SEND_SAFETY_CENTER_UPDATE :

boolean isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled();
if (isSafetyCenterEnabled) {
  // …
} else {
  // …
}

Cung cấp dữ liệu

Dữ liệu nguồn của Trung tâm An toàn có String sourceId đã cho được cung cấp cho Trung tâm An toàn cùng với đối tượng SafetySourceData , đại diện cho một mục nhập giao diện người dùng và danh sách các vấn đề (thẻ cảnh báo). Mục nhập giao diện người dùng và thẻ cảnh báo có thể có mức độ nghiêm trọng khác nhau được chỉ định trong lớp SafetySourceData :

  • SEVERITY_LEVEL_UNSPECIFIED
    • Không có mức độ nghiêm trọng được chỉ định
    • Màu sắc: Xám hoặc trong suốt (tùy thuộc vào Nhóm SafetySourcesGroup của mục nhập)
    • Được sử dụng cho dữ liệu động đóng vai trò là mục nhập tĩnh trong giao diện người dùng hoặc để hiển thị mục nhập không xác định
    • Không được sử dụng làm thẻ cảnh báo
  • SEVERITY_LEVEL_INFORMATION
    • Thông tin cơ bản hoặc gợi ý nhỏ
    • Màu xanh lá cây
  • SEVERITY_LEVEL_RECOMMENDATION
    • Khuyến nghị người dùng nên hành động về vấn đề này vì nó có thể khiến họ gặp rủi ro
    • Màu vàng
  • SEVERITY_LEVEL_CRITICAL_WARNING
    • Cảnh báo nghiêm trọng rằng người dùng phải thực hiện hành động đối với vấn đề này vì nó gây ra rủi ro
    • Màu đỏ

SafetySourceData

Đối tượng SafetySourceData bao gồm một mục nhập giao diện người dùng, thẻ cảnh báo và các bất biến.

  • Phiên bản SafetySourceStatus tùy chọn (mục nhập giao diện người dùng)
  • Danh sách các phiên bản SafetySourceIssue (thẻ cảnh báo)
  • Bundle bổ sung tùy chọn (Bắt đầu từ 14)
  • Bất biến:
    • Danh sách SafetySourceIssue phải bao gồm các vấn đề có mã định danh duy nhất.
    • Phiên bản SafetySourceIssue không được có tầm quan trọng lớn hơn SafetySourceStatus nếu có (trừ khi SafetySourceStatusSEVERITY_LEVEL_UNSPECIFIED , trong trường hợp đó vấn đề SEVERITY_LEVEL_INFORMATION được cho phép).
    • Các yêu cầu bổ sung do cấu hình API đặt ra phải được đáp ứng, ví dụ: nếu nguồn chỉ có vấn đề thì nguồn đó không được cung cấp phiên bản SafetySourceStatus .

SafetySourceStatus

  • Tiêu đề CharSequence bắt buộc
  • Tóm tắt CharSequence bắt buộc
  • Mức độ nghiêm trọng cần thiết
  • Phiên bản PendingIntent tùy chọn để chuyển hướng người dùng đến đúng trang (mặc định sử dụng intentAction từ cấu hình, nếu có)
  • IconAction tùy chọn (hiển thị dưới dạng biểu tượng bên trên mục nhập) bao gồm:
    • Loại biểu tượng bắt buộc, phải là một trong các loại sau:
      • ICON_TYPE_GEAR : Hiển thị dưới dạng bánh răng bên cạnh mục nhập UI
      • ICON_TYPE_INFO : Hiển thị dưới dạng biểu tượng thông tin bên cạnh mục nhập UI
    • Bắt buộc PendingIntent để chuyển hướng người dùng đến một trang khác
  • Giá trị enabled boolean tùy chọn cho phép đánh dấu mục nhập UI là bị vô hiệu hóa, do đó không thể nhấp vào được (mặc định là true )
  • Bất biến:
    • Các phiên bản PendingIntent phải mở một phiên bản Activity .
    • Nếu mục nhập bị tắt, nó phải được chỉ định SEVERITY_LEVEL_UNSPECIFIED .
    • Các yêu cầu bổ sung do cấu hình API áp đặt.

SafetySourceIssue

  • Mã định danh String duy nhất bắt buộc
  • Tiêu đề CharSequence bắt buộc
  • Phụ đề CharSequence tùy chọn
  • Tóm tắt CharSequence bắt buộc
  • Mức độ nghiêm trọng cần thiết
  • Danh mục vấn đề tùy chọn, phải là một trong:
    • ISSUE_CATEGORY_DEVICE : Sự cố ảnh hưởng đến thiết bị của người dùng.
    • ISSUE_CATEGORY_ACCOUNT : Sự cố ảnh hưởng đến tài khoản của người dùng.
    • ISSUE_CATEGORY_GENERAL : Sự cố ảnh hưởng đến sự an toàn chung của người dùng. Đây là mặc định.
    • ISSUE_CATEGORY_DATA (Khởi động Android 14): Sự cố ảnh hưởng đến dữ liệu của người dùng.
    • ISSUE_CATEGORY_PASSWORDS (Khởi động Android 14): Sự cố ảnh hưởng đến mật khẩu của người dùng.
    • ISSUE_CATEGORY_PERSONAL_SAFETY (Khởi động Android 14): Sự cố ảnh hưởng đến sự an toàn cá nhân của người dùng.
  • Danh sách các thành phần Action mà người dùng có thể thực hiện đối với sự cố này, mỗi phiên bản Action bao gồm:
    • Mã định danh String duy nhất bắt buộc
    • Nhãn CharSequence bắt buộc
    • Bắt buộc PendingIntent chuyển hướng người dùng đến một trang khác hoặc xử lý hành động trực tiếp từ màn hình Trung tâm an toàn
    • Boolean tùy chọn để chỉ định xem vấn đề này có thể được giải quyết trực tiếp từ màn hình Trung tâm an toàn hay không (mặc định là false )
    • Thông báo thành công CharSequence tùy chọn, sẽ được hiển thị cho người dùng khi sự cố được giải quyết thành công trực tiếp từ màn hình Trung tâm an toàn
  • PendingIntent tùy chọn được gọi khi người dùng loại bỏ sự cố (mặc định là không có gì được gọi)
  • Mã định danh loại vấn đề String bắt buộc; cái này tương tự với mã định danh vấn đề nhưng không nhất thiết phải là duy nhất và được sử dụng để ghi nhật ký
  • Chuỗi String chọn cho id loại bỏ trùng lặp, điều này cho phép đăng cùng một SafetySourceIssue từ các nguồn khác nhau và chỉ hiển thị nó một lần trong giao diện người dùng giả định rằng chúng có cùng deduplicationGroup (Bắt đầu từ Android 14). Nếu không được chỉ định, vấn đề sẽ không bao giờ bị trùng lặp
  • CharSequence tùy chọn cho tiêu đề phân bổ, đây là văn bản cho biết nguồn gốc của thẻ cảnh báo (Bắt đầu từ Android 14). Nếu không được chỉ định, hãy sử dụng tiêu đề của SafetySourcesGroup
  • Khả năng xử lý sự cố tùy chọn (Khởi động Android 14), phải là một trong:
    • ISSUE_ACTIONABILITY_MANUAL : Người dùng cần giải quyết vấn đề này theo cách thủ công. Đây là mặc định.
    • ISSUE_ACTIONABILITY_TIP : Vấn đề này chỉ là một mẹo và có thể không yêu cầu bất kỳ thông tin đầu vào nào của người dùng.
    • ISSUE_ACTIONABILITY_AUTOMATIC : Sự cố này đã được xử lý và có thể không yêu cầu bất kỳ thông tin đầu vào nào của người dùng.
  • Hành vi thông báo tùy chọn (Khởi động Android 14), phải là một trong:
    • NOTIFICATION_BEHAVIOR_UNSPECIFIED : Trung tâm An toàn sẽ quyết định xem có cần thông báo cho thẻ cảnh báo hay không. Đây là mặc định.
    • NOTIFICATION_BEHAVIOR_NEVER : Không có thông báo nào được đăng.
    • NOTIFICATION_BEHAVIOR_DELAYED : Thông báo được đăng một thời gian sau khi sự cố được báo cáo lần đầu.
    • NOTIFICATION_BEHAVIOR_IMMEDIATELY : Thông báo được đăng ngay khi sự cố được báo cáo.
  • Notification tùy chọn, để hiển thị thông báo tùy chỉnh kèm theo thẻ cảnh báo (Bắt đầu từ Android 14). Nếu không được chỉ định, Notification sẽ được lấy từ thẻ cảnh báo. Gồm:
    • Tiêu đề CharSequence bắt buộc
    • Tóm tắt CharSequence bắt buộc
    • Danh sách các yếu tố Action mà người dùng có thể thực hiện cho thông báo này
  • Bất biến:
    • Danh sách các phiên bản Action phải bao gồm các hành động có mã định danh duy nhất
    • Danh sách các phiên bản Action phải chứa một hoặc hai phần tử Action . Nếu khả năng hành động không phải là ISSUE_ACTIONABILITY_MANUAL thì không được phép có Action nào.
    • OnDismiss PendingIntent không được mở phiên bản Activity
    • Các yêu cầu bổ sung do cấu hình API áp đặt

Dữ liệu được cung cấp theo một số sự kiện nhất định cho Trung tâm An toàn, do đó, cần phải chỉ rõ nguyên nhân khiến nguồn cung cấp phiên bản SafetySourceData với phiên bản SafetyEvent .

SafetyEvent

  • Loại bắt buộc, phải là một trong:
    • SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED : Trạng thái của nguồn đã thay đổi.
    • SAFETY_EVENT_TYPE_REFRESH_REQUESTED : Phản hồi tín hiệu làm mới/quét lại từ Trung tâm an toàn; hãy sử dụng tùy chọn này thay vì SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED cho Trung tâm an toàn để có thể theo dõi yêu cầu làm mới/quét lại.
    • SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED : Chúng tôi đã giải quyết SafetySourceIssue.Action trực tiếp từ màn hình Trung tâm An toàn; hãy sử dụng tùy chọn này thay vì SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED cho Trung tâm an toàn để có thể theo dõi SafetySourceIssue.Action đang được giải quyết.
    • SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED : Chúng tôi đã cố gắng giải quyết SafetySourceIssue.Action trực tiếp từ màn hình Trung tâm an toàn nhưng không thực hiện được; hãy sử dụng tùy chọn này thay vì SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED cho Trung tâm an toàn để có thể theo dõi SafetySourceIssue.Action không thành công.
    • SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED : Ngôn ngữ của thiết bị đã thay đổi, vì vậy chúng tôi đang cập nhật nội dung của dữ liệu được cung cấp; được phép sử dụng SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED cho việc này.
    • SAFETY_EVENT_TYPE_DEVICE_REBOOTED : Chúng tôi đang cung cấp dữ liệu này như một phần của lần khởi động đầu tiên vì dữ liệu của Trung tâm An toàn không được lưu giữ trong các lần khởi động lại; được phép sử dụng SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED cho việc này.
  • Mã định danh String chọn cho ID quảng bá làm mới.
  • Mã định danh String chọn cho phiên bản SafetySourceIssue đang được giải quyết.
  • Mã định danh String chọn cho phiên bản SafetySourceIssue.Action đang được giải quyết.
  • Bất biến:
    • ID phát sóng làm mới phải được cung cấp nếu loại là SAFETY_EVENT_TYPE_REFRESH_REQUESTED
    • ID vấn đề và hành động phải được cung cấp nếu loại là SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED hoặc SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED

Dưới đây là ví dụ về cách một nguồn có thể cung cấp dữ liệu cho Trung tâm An toàn (trong trường hợp này là cung cấp một mục nhập có một thẻ cảnh báo):

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);

Nhận dữ liệu cuối cùng được cung cấp

Bạn có thể lấy dữ liệu cuối cùng được cung cấp cho Trung tâm an toàn cho nguồn do ứng dụng của bạn sở hữu. Bạn có thể sử dụng tính năng này để hiển thị nội dung nào đó trong giao diện người dùng của riêng mình, để kiểm tra xem dữ liệu có cần được cập nhật trước khi thực hiện một thao tác tốn kém hay để cung cấp cùng một phiên bản SafetySourceData cho Trung tâm an toàn với một số thay đổi hoặc với một phiên bản SafetyEvent mới. Nó cũng hữu ích cho việc thử nghiệm.

Sử dụng mã này để lấy dữ liệu cuối cùng được cung cấp cho Trung tâm An toàn:

SafetySourceData lastDataProvided = safetyCenterManager.getSafetySourceData("MySourceId");

Báo cáo lỗi

Nếu không thể thu thập dữ liệu SafetySourceData , bạn có thể báo cáo lỗi cho Trung tâm an toàn. Trung tâm này sẽ thay đổi mục nhập thành màu xám, xóa dữ liệu được lưu trong bộ nhớ đệm và cung cấp thông báo như Không thể kiểm tra cài đặt . Bạn cũng có thể báo cáo lỗi nếu một phiên bản của SafetySourceIssue.Action không giải quyết được, trong trường hợp đó dữ liệu được lưu trong bộ nhớ đệm không bị xóa và mục nhập giao diện người dùng không bị thay đổi; nhưng một thông báo được hiển thị cho người dùng để cho họ biết rằng đã xảy ra sự cố.

Bạn có thể cung cấp lỗi bằng cách sử dụng SafetySourceErrorDetails , bao gồm:

  • SafetySourceErrorDetails : Phiên bản SafetyEvent bắt buộc :
// 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);

Trả lời yêu cầu làm mới hoặc quét lại

Bạn có thể nhận được tín hiệu từ Trung tâm an toàn để cung cấp dữ liệu mới. Việc phản hồi yêu cầu làm mới hoặc quét lại đảm bảo rằng người dùng xem trạng thái hiện tại khi mở Trung tâm an toàn và khi họ chạm vào nút quét.

Điều này được thực hiện bằng cách nhận một chương trình phát sóng với hành động sau:

  • ACTION_REFRESH_SAFETY_SOURCES
    • Giá trị chuỗi: android.safetycenter.action.REFRESH_SAFETY_SOURCES
    • Được kích hoạt khi Trung tâm an toàn gửi yêu cầu làm mới dữ liệu của nguồn an toàn cho một ứng dụng nhất định
    • Mục đích được bảo vệ chỉ có thể được gửi bởi hệ thống
    • Được gửi tới tất cả các nguồn an toàn trong tệp cấu hình dưới dạng mục đích rõ ràng và yêu cầu quyền SEND_SAFETY_CENTER_UPDATE

Các tính năng bổ sung sau đây được cung cấp như một phần của chương trình phát sóng này:

  • EXTRA_REFRESH_SAFETY_SOURCE_IDS
    • Giá trị chuỗi: android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
    • Kiểu mảng chuỗi ( String[] ), biểu thị ID nguồn cần làm mới cho ứng dụng nhất định
  • EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE

    • Giá trị chuỗi: android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
    • Kiểu số nguyên, đại diện cho loại yêu cầu @IntDef
    • Phải là một trong:
      • EXTRA_REFRESH_REQUEST_TYPE_GET_DATA : Yêu cầu nguồn cung cấp dữ liệu tương đối nhanh, điển hình là khi người dùng mở trang
      • EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA : Yêu cầu nguồn cung cấp dữ liệu mới nhất có thể, thường là khi người dùng nhấn nút quét lại
  • EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID

    • Giá trị chuỗi: android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
    • Loại chuỗi, đại diện cho một mã định danh duy nhất cho lần làm mới được yêu cầu

Để nhận tín hiệu từ Trung tâm an toàn, hãy triển khai phiên bản BroadcastReceiver . Chương trình phát sóng được gửi với BroadcastOptions đặc biệt cho phép người nhận bắt đầu dịch vụ nền trước.

BroadcastReceiver đáp ứng yêu cầu làm mới:

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;
  }
}

Phiên bản tương tự của BroadcastReceiver trong ví dụ trên được khai báo trong 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>

Lý tưởng nhất là nguồn Trung tâm an toàn được triển khai theo cách nó gọi SafetyCenterManager khi dữ liệu của nó thay đổi. Vì lý do sức khỏe hệ thống, chúng tôi khuyên bạn chỉ nên phản hồi tín hiệu quét lại (khi người dùng nhấn vào nút quét) chứ không phải khi người dùng mở Trung tâm an toàn. Nếu chức năng này là bắt buộc thì trường refreshOnPageOpenAllowed="true" trong tệp cấu hình phải được đặt cho nguồn nhận chương trình phát sóng được phân phối trong những trường hợp này.

Trả lời Trung tâm an toàn khi được bật hoặc tắt

Bạn có thể phản hồi khi bật hoặc tắt Trung tâm an toàn bằng cách sử dụng hành động theo ý định sau:

  • ACTION_SAFETY_CENTER_ENABLED_CHANGED
    • Giá trị chuỗi: android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
    • Được kích hoạt khi Trung tâm an toàn được bật hoặc tắt trong khi thiết bị đang chạy
    • Không được gọi khi khởi động (sử dụng ACTION_BOOT_COMPLETED cho việc đó)
    • Mục đích được bảo vệ chỉ có thể được gửi bởi hệ thống
    • Được gửi tới tất cả các nguồn an toàn trong tệp cấu hình dưới dạng mục đích rõ ràng, cần có quyền SEND_SAFETY_CENTER_UPDATE
    • Được gửi dưới dạng mục đích ngầm yêu cầu quyền READ_SAFETY_CENTER_STATUS

Hành động theo ý định này rất hữu ích để bật hoặc tắt các tính năng liên quan đến Trung tâm an toàn trên thiết bị.

Thực hiện các hành động giải quyết

Hành động giải quyết là một phiên bản SafetySourceIssue.Action mà người dùng có thể giải quyết trực tiếp từ màn hình Trung tâm an toàn. Người dùng nhấn vào nút hành động và phiên bản PendingIntent trên SafetySourceIssue.Action . Hành động do nguồn an toàn gửi sẽ được kích hoạt, giải quyết sự cố ở chế độ nền và thông báo cho Trung tâm An toàn khi hoàn tất.

Để triển khai các hành động giải quyết, nguồn Trung tâm an toàn có thể sử dụng một dịch vụ nếu thao tác dự kiến ​​sẽ mất một chút thời gian ( PendingIntent.getService ) hoặc bộ thu quảng bá ( PendingIntent.getBroadcast ).

Sử dụng mã này để gửi vấn đề đang giải quyết đến Trung tâm an toàn:

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 giải quyết hành động:

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).
  }
}

Phiên bản tương tự của BroadcastReceiver trong ví dụ trên được khai báo trong 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>

Trả lời vấn đề sa thải

Bạn có thể chỉ định một phiên bản PendingIntent có thể được kích hoạt khi một phiên bản SafetySourceIssue bị loại bỏ. Trung tâm An toàn xử lý các trường hợp loại bỏ sau:

  • Nếu nguồn đưa ra một vấn đề, người dùng có thể loại bỏ vấn đề đó trên màn hình Trung tâm An toàn bằng cách nhấn vào nút loại bỏ (nút X trên thẻ cảnh báo).
  • Khi người dùng loại bỏ một vấn đề, nếu sự cố đó tiếp tục thì vấn đề đó sẽ không hiển thị lại trong giao diện người dùng.
  • Việc loại bỏ liên tục trên đĩa vẫn còn trong quá trình khởi động lại thiết bị.
  • Nếu nguồn Trung tâm an toàn ngừng cung cấp sự cố rồi cung cấp lại sự cố sau đó thì sự cố sẽ lại xuất hiện. Điều này nhằm cho phép các tình huống trong đó người dùng nhìn thấy cảnh báo, loại bỏ cảnh báo đó, sau đó thực hiện hành động giúp giảm bớt sự cố nhưng sau đó người dùng lại làm điều gì đó gây ra sự cố tương tự. Tại thời điểm này, thẻ cảnh báo sẽ xuất hiện trở lại.
  • Thẻ cảnh báo màu vàng và đỏ sẽ xuất hiện lại sau mỗi 180 ngày trừ khi người dùng đã loại bỏ chúng nhiều lần.

Nguồn không cần phải có các hành vi bổ sung trừ khi:

  • Ví dụ: nguồn cố gắng triển khai hành vi này theo cách khác, không bao giờ tái hiện vấn đề.
  • Nguồn cố gắng sử dụng điều này như một lệnh gọi lại, chẳng hạn như để ghi nhật ký thông tin.

Cung cấp dữ liệu cho nhiều người dùng/hồ sơ

API SafetyCenterManager có thể được sử dụng cho nhiều người dùng và hồ sơ. Để biết thêm thông tin, hãy xem Xây dựng ứng dụng nhận biết nhiều người dùng . Đối tượng Context cung cấp SafetyCenterManager được liên kết với một phiên bản UserHandle , do đó, phiên bản SafetyCenterManager được trả về sẽ tương tác với Trung tâm An toàn cho phiên bản UserHandle đó. Theo mặc định, Context được liên kết với người dùng đang chạy nhưng có thể tạo một phiên bản cho người dùng khác nếu ứng dụng có các quyền INTERACT_ACROSS_USERSINTERACT_ACROSS_USERS_FULL . Ví dụ này cho thấy việc thực hiện cuộc gọi giữa người dùng/hồ sơ:

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

Mỗi người dùng trên thiết bị có thể có nhiều hồ sơ được quản lý. Trung tâm An toàn cung cấp dữ liệu khác nhau cho mỗi người dùng nhưng hợp nhất dữ liệu của tất cả hồ sơ được quản lý liên kết với một người dùng nhất định.

Khi profile="all_profiles" được đặt cho nguồn trong tệp cấu hình, điều sau sẽ xảy ra:

  • Có một mục nhập giao diện người dùng cho người dùng (hồ sơ gốc) và tất cả các hồ sơ được quản lý liên kết của nó (sử dụng phiên bản titleForWork ).
  • Tín hiệu làm mới hoặc quét lại được gửi cho hồ sơ gốc và tất cả các hồ sơ được quản lý liên quan. Bộ thu được liên kết được khởi động cho từng hồ sơ và có thể cung cấp dữ liệu liên quan trực tiếp đến SafetyCenterManager mà không cần phải thực hiện lệnh gọi giữa các cấu hình trừ khi bộ thu hoặc ứng dụng là singleUser .

  • Nguồn dự kiến ​​​​sẽ cung cấp dữ liệu cho người dùng và tất cả hồ sơ được quản lý của nó. Dữ liệu cho mỗi mục nhập giao diện người dùng có thể khác nhau tùy thuộc vào hồ sơ.

Kiểm tra

bạn có thể truy cập ShadowSafetyCenterManager và sử dụng nó trong thử nghiệm 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);
}

Bạn có thể viết nhiều bài kiểm tra end-to-end (E2E) hơn, nhưng điều đó nằm ngoài phạm vi của hướng dẫn này. Để biết thêm thông tin về cách viết các bài kiểm tra E2E này, hãy xem các bài kiểm tra CTS (CtsSafetyCenterTestCase)

API thử nghiệm và nội bộ

API nội bộ và API thử nghiệm được sử dụng nội bộ nên không được mô tả chi tiết trong hướng dẫn này. Tuy nhiên, chúng tôi có thể mở rộng một số API nội bộ trong tương lai để cho phép các OEM xây dựng giao diện người dùng của riêng họ và chúng tôi sẽ cập nhật hướng dẫn này để cung cấp hướng dẫn về cách sử dụng chúng.

Quyền

  • MANAGE_SAFETY_CENTER
    • internal|installer|role
    • Được sử dụng cho API Trung tâm An toàn nội bộ
    • Chỉ được cấp cho PermissionController và shell

Ứng dụng cài đặt

Chuyển hướng Trung tâm an toàn

Theo mặc định, Trung tâm an toàn được truy cập thông qua ứng dụng Cài đặt với mục Bảo mật & quyền riêng tư mới. Nếu bạn sử dụng một ứng dụng Cài đặt khác hoặc nếu bạn đã sửa đổi ứng dụng Cài đặt thì bạn có thể cần tùy chỉnh cách truy cập Trung tâm An toàn.

Khi Trung tâm an toàn được bật:

  • Mục nhập Quyền riêng tư kế thừa là ẩn
  • Mục bảo mật kế thừa là ẩn
  • Mục bảo mật và quyền riêng tư mới được thêm
  • Mục nhập Bảo mật & quyền riêng tư mới chuyển hướng đến Trung tâm An toàn
  • android.settings.PRIVACY_SETTINGSandroid.settings.SECURITY_SETTINGS các hành động có ý định được chuyển hướng đến Trung tâm an toàn mở (mã: security , Privacy )

Trang bảo mật và quyền riêng tư nâng cao

Ứng dụng Cài đặt chứa các cài đặt bổ sung trong Cài đặt bảo mật khác và Tiêu đề cài đặt quyền riêng tư khác , có sẵn từ Trung tâm an toàn:

Nguồn an toàn

Trung tâm An toàn tích hợp với một nhóm nguồn an toàn cụ thể do ứng dụng Cài đặt cung cấp:

  • Nguồn an toàn màn hình khóa xác minh rằng màn hình khóa được thiết lập bằng mật mã (hoặc biện pháp bảo mật khác) để đảm bảo rằng thông tin riêng tư của người dùng được giữ an toàn trước sự truy cập từ bên ngoài.
  • Nguồn an toàn sinh trắc học (ẩn theo mặc định) sẽ tích hợp với cảm biến vân tay hoặc khuôn mặt.

Bạn có thể truy cập mã nguồn của các nguồn Trung tâm an toàn này thông qua tìm kiếm mã Android . Nếu ứng dụng Cài đặt không được sửa đổi (các thay đổi không được thực hiện đối với tên gói, mã nguồn hoặc mã nguồn liên quan đến màn hình khóa và sinh trắc học), thì việc tích hợp này sẽ hoạt động tốt. Nếu không, có thể cần phải thực hiện một số sửa đổi, chẳng hạn như thay đổi tệp cấu hình để thay đổi tên gói của ứng dụng Cài đặt và các nguồn tích hợp với Trung tâm An toàn cũng như phần tích hợp. Để biết thêm thông tin, hãy xem Cập nhật tệp cấu hìnhcài đặt tích hợp .

Giới thiệu về ý định đang chờ xử lý

Nếu bạn dựa vào tính năng tích hợp Trung tâm an toàn của ứng dụng Cài đặt hiện có trong Android 14 trở lên thì lỗi mô tả bên dưới đã được khắc phục. Đọc phần này là không cần thiết trong trường hợp này.

Khi bạn chắc chắn rằng lỗi không tồn tại, hãy đặt giá trị cấu hình tài nguyên boolean XML trong ứng dụng Cài đặt config_isSafetyCenterLockScreenPendingIntentFixed thành true để tắt giải pháp thay thế trong Trung tâm an toàn.

Cách giải quyết có chủ ý đang chờ xử lý

Lỗi này xảy ra do Cài đặt sử dụng phần bổ sung phiên bản Intent để xác định đoạn nào sẽ mở. Vì Intent#equals không tính đến các phần bổ sung của phiên bản Intent nên phiên bản PendingIntent cho biểu tượng menu bánh răng và mục nhập được coi là bằng nhau và điều hướng đến cùng một giao diện người dùng (mặc dù chúng có ý định điều hướng đến một giao diện người dùng khác). Sự cố này đã được khắc phục trong bản phát hành QPR bằng cách phân biệt các phiên bản PendingIntent theo mã yêu cầu. Ngoài ra, điều này có thể được phân biệt bằng cách sử dụng Intent#setId .

Nguồn an toàn nội bộ

Một số nguồn của Trung tâm an toàn là nội bộ và được triển khai trong ứng dụng hệ thống PermissionController bên trong mô-đun PermissionController. Những nguồn này hoạt động giống như các nguồn của Trung tâm An toàn thông thường và không được xử lý đặc biệt. Mã cho các nguồn này có sẵn thông qua tìm kiếm mã Android .

Đây chủ yếu là các tín hiệu về quyền riêng tư, ví dụ:

  • Khả năng tiếp cận
  • Tự động thu hồi các ứng dụng không sử dụng
  • Quyền truy cập vị trí
  • Người nghe thông báo
  • Thông tin chính sách làm việc