Chuyển hướng đến Trung tâm an toàn
Mọi ứng dụng đều có thể mở Trung tâm an toàn bằng thao tác android.content.Intent.ACTION_SAFETY_CENTER
(giá trị chuỗi android.intent.action.SAFETY_CENTER
).
Để mở Trung tâm an toàn, hãy gọi điện trong một thực thể 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 một thẻ cảnh báo cụ thể trong Trung tâm an toàn bằng cách sử dụng các ý định bổ sung cụ thể. Các dữ liệu bổ sung này không dành cho bên thứ ba sử dụng, vì vậy, chúng thuộc SafetyCenterManager
(một phần của @SystemApi
). Chỉ các ứng dụng hệ thống mới có thể truy cập vào các tính năng bổ sung này.
Các ý định bổ sung 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 mã nhận dạng nguồn an toàn của thẻ cảnh báo được liên kết
- Bắt buộc để chuyển hướng đến vấn đề để hoạt động
- Giá trị chuỗi:
EXTRA_SAFETY_SOURCE_ISSUE_ID
- Giá trị chuỗi:
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- Loại chuỗi: Chỉ định mã thẻ cảnh báo
- Bắt buộc để chuyển hướng đến vấn đề để hoạt động
- Giá trị chuỗi:
EXTRA_SAFETY_SOURCE_USER_HANDLE
- Giá trị chuỗi:
android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
- Loại
UserHandle
: Chỉ địnhUserHandle
cho thẻ cảnh báo liên kết - Không bắt buộc (mặc định là người dùng hiện tại)
- Giá trị chuỗi:
Bạn có thể sử dụng đoạn mã dưới đây từ trong một thực thể 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ể (Kể từ Android 14)
Trên 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 sẽ hiển thị dưới dạng các mục có thể thu gọn).
Bạn có thể chuyển hướng đến một trang con cụ thể bằng cách sử dụng ý định bổ sung này:
EXTRA_SAFETY_SOURCES_GROUP_ID
- Giá trị chuỗi:
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- Loại chuỗi: Chỉ định mã nhận dạng của
SafetySourcesGroup
- Bắt buộc để chuyển hướng đến trang con để hoạt động
- Giá trị chuỗi:
Bạn có thể sử dụng đoạn mã dưới đây trong một thực thể Activity
để mở màn hình Trung tâm an toàn đến 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
Bạn có thể sử dụng SafetyCenterManager
(là một @SystemApi
) để sử dụng các API nguồn của Trung tâm an toàn. Mã cho giao diện API có trong tính năng Tìm kiếm mã.
Bạn có thể tìm thấy mã triển khai của các API trong tính năng Tìm kiếm mã.
Quyền
Chỉ các ứng dụng hệ thống trong danh sách cho phép mới có thể truy cập vào API nguồn của Trung tâm an toàn bằng các quyền nêu dưới đây. Để biết thêm thông tin, hãy xem Danh sách cho phép các đặc quyền.
READ_SAFETY_CENTER_STATUS
signature|privileged
- Dùng cho API
SafetyCenterManager#isSafetyCenterEnabled()
(không cần thiết cho các nguồn Safety Center, chúng chỉ cần quyềnSEND_SAFETY_CENTER_UPDATE
) - Dùng trong những ứ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
- Dùng cho API đã bật và API Nguồn an toàn
- Chỉ những nguồn an toàn mới được dùng
- 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ể lấy được bằng cách thêm các quyền đó vào tệp có liên quan, chẳng hạn như tệp com.android.settings.xml
cho ứng dụng Cài đặt và tệp AndroidManifest.xml
của ứng dụng. Hãy xem protectionLevel
để biết thêm thông tin về mô hình quản lý quyền.
Tải SafetyCenterManager
SafetyCenterManager
là một lớp @SystemApi
có thể truy cập được qua các ứng dụng hệ thống kể từ Android 13. Lệnh gọi này minh hoạ cách lấy 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 bật chưa
Cuộc gọi này kiểm tra xem Trung tâm an toàn đã được bật hay chưa. Lệnh gọi yêu cầu quyền READ_SAFETY_CENTER_STATUS
hoặc 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
nhất định được cung cấp cho Trung tâm an toàn kèm theo đối tượng SafetySourceData
. Đối tượng này đại diện cho một mục trên 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ó các mức độ nghiêm trọng khác nhau được chỉ định trong lớp SafetySourceData
:
SEVERITY_LEVEL_UNSPECIFIED
- Chưa chỉ định mức độ nghiêm trọng
- Màu: Xám hoặc trong suốt (tuỳ thuộc vào
SafetySourcesGroup
của mục nhập) - 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ột mục nhập không xác định
- Không được dùng cho thẻ cảnh báo
SEVERITY_LEVEL_INFORMATION
- Thông tin cơ bản hoặc đề xuất nhỏ
- Màu: Xanh lục
SEVERITY_LEVEL_RECOMMENDATION
- Đề xuất rằng người dùng nên thực hiện hành động đối với vấn đề này, vì điều này có thể khiến họ gặp rủi ro
- Màu: Vàng
SEVERITY_LEVEL_CRITICAL_WARNING
- Cảnh báo quan trọng về việc người dùng phải xử lý vấn đề này vì vấn đề này có thể gây ra rủi ro
- Màu: Đỏ
SafetySourceData
Đối tượng SafetySourceData
bao gồm một mục giao diện người dùng, thẻ cảnh báo và các thuộc tính bất biến.
- Thực thể
SafetySourceStatus
không bắt buộc (mục nhập giao diện người dùng) - Danh sách
SafetySourceIssue
thực thể (thẻ cảnh báo) - Các thành phần bổ sung
Bundle
không bắt buộc (Kể từ phiên bản 14) - Biến không đổi:
- Danh sách
SafetySourceIssue
phải bao gồm các vấn đề có giá trị nhận dạng duy nhất. - Thực thể
SafetySourceIssue
không được có tầm quan trọng lớn hơnSafetySourceStatus
nếu có (trừ phiSafetySourceStatus
làSEVERITY_LEVEL_UNSPECIFIED
, trong trường hợp này thì các vấn đề vềSEVERITY_LEVEL_INFORMATION
sẽ được cho phép). - Bạn phải đáp ứng các yêu cầu bổ sung do cấu hình API đặt ra, ví dụ: nếu nguồn chỉ xảy ra sự cố, thì nguồn đó không được cung cấp thực thể
SafetySourceStatus
.
- Danh sách
SafetySourceStatus
- Tiêu đề
CharSequence
bắt buộc - Tóm tắt
CharSequence
bắt buộc - Mức độ nghiêm trọng bắt buộc
- Thực thể
PendingIntent
(không bắt buộc) để chuyển hướng người dùng đến đúng trang (mặc định sử dụngintentAction
từ cấu hình, nếu có) IconAction
không bắt buộc (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
: Xuất hiện dưới dạng một bánh răng bên cạnh mục nhập giao diện người dùngICON_TYPE_INFO
: Hiển thị dưới dạng biểu tượng thông tin bên cạnh mục nhập giao diện người dùng
- Bắt buộc
PendingIntent
để chuyển hướng người dùng đến một trang khác
- Loại biểu tượng bắt buộc phải là một trong các loại sau:
- Giá trị
enabled
boolean không bắt buộc cho phép đánh dấu mục nhập giao diện người dùng là bị vô hiệu hoá, vì vậy, mục nhập này không thể nhấp vào (mặc định làtrue
) - Bất biến:
- Các thực thể
PendingIntent
phải mở một thực thểActivity
. - Nếu mục nhập bị tắt, bạn phải chỉ định mục đó là
SEVERITY_LEVEL_UNSPECIFIED
. - Các yêu cầu bổ sung do cấu hình API áp đặt.
- Các thực thể
SafetySourceIssue
- Giá trị nhận dạng
String
duy nhất bắt buộc - Tiêu đề
CharSequence
bắt buộc - Tiêu đề phụ
CharSequence
không bắt buộc - Tóm tắt
CharSequence
bắt buộc - Mức độ nghiêm trọng bắt buộc
- Danh mục vấn đề không bắt buộc, phải là một trong các loại sau:
ISSUE_CATEGORY_DEVICE
: Vấn đề ảnh hưởng đến thiết bị của người dùng.ISSUE_CATEGORY_ACCOUNT
: Vấn đề này ảnh hưởng đến các tài khoản của người dùng.ISSUE_CATEGORY_GENERAL
: Vấn đề ảnh hưởng đến sự an toàn chung của người dùng. Đây là tuỳ chọn mặc định.ISSUE_CATEGORY_DATA
(Kể từ Android 14): Vấn đề ảnh hưởng đến dữ liệu của người dùng.ISSUE_CATEGORY_PASSWORDS
(Kể từ Android 14): Sự cố này ảnh hưởng đến mật khẩu của người dùng.ISSUE_CATEGORY_PERSONAL_SAFETY
(Kể từ Android 14): Vấn đề này ảnh hưởng đến sự an toàn cá nhân của người dùng.
- Danh sách các phần tử
Action
mà người dùng có thể sử dụng cho vấn đề này, mỗi thực thểAction
bao gồm:- Giá trị nhận dạng
String
duy nhất bắt buộc - Nhãn
CharSequence
bắt buộc - Bắt buộc phải có
PendingIntent
để chuyển hướng người dùng đến một trang khác hoặc xử lý hành động ngay trên màn hình Trung tâm an toàn - Giá trị boolean không bắt buộc để chỉ định xem bạn có thể giải quyết vấn đề này trực tiếp trên màn hình SafetyCenter hay không (mặc định là
false
) - Thông báo thành công
CharSequence
không bắt buộc, sẽ hiển thị cho người dùng khi sự cố được giải quyết thành công ngay trên màn hình Trung tâm an toàn
- Giá trị nhận dạng
PendingIntent
không bắt buộc được gọi khi người dùng đóng vấn đề (mặc định là không có lệnh gọi nào)- Giá trị nhận dạng loại vấn đề
String
bắt buộc; giá trị này tương tự như giá trị nhận dạng vấn đề nhưng không nhất thiết phải là duy nhất và được dùng để ghi nhật ký String
không bắt buộc cho mã nhận dạng loại bỏ trùng lặp, điều này cho phép đăng cùng mộtSafetySourceIssue
từ nhiều nguồn và chỉ hiển thị một lần trong giao diện người dùng giả sử chúng có cùng mộtdeduplicationGroup
(Kể từ Android 14). Nếu không được chỉ định, vấn đề sẽ không bao giờ được loại bỏ trùng lặpCharSequence
không bắt buộc cho tiêu đề thuộc tính, đây là văn bản cho biết nguồn gốc của thẻ cảnh báo (Kể từ Android 14). Nếu không chỉ định, hãy sử dụng tiêu đề củaSafetySourcesGroup
- Khả năng hành động đối với vấn đề (Không bắt buộc, bắt đầu từ Android 14), phải là một trong những lựa chọn sau:
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à tuỳ chọn 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 người dùng nhập bất kỳ thông tin nào.ISSUE_ACTIONABILITY_AUTOMATIC
: Vấn đề này đã được xử lý và có thể không cần người dùng thực hiện hành động nào.
- Hành vi thông báo không bắt buộc (Kể từ Android 14), phải là một trong các hành vi sau:
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à tuỳ chọn 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 sau một khoảng thời gian kể từ lần đầu tiên báo cáo vấn đề.NOTIFICATION_BEHAVIOR_IMMEDIATELY
: Thông báo sẽ được đăng ngay khi vấn đề được báo cáo.
Notification
không bắt buộc để hiển thị thông báo tuỳ chỉnh cùng với thẻ cảnh báo (Kể từ Android 14). Nếu không được chỉ định,Notification
sẽ được lấy từ thẻ cảnh báo. Bao gồm:- Tiêu đề
CharSequence
bắt buộc - Thông tin tóm tắt bắt buộc về
CharSequence
- Danh sách các phần tử
Action
mà người dùng có thể thực hiện đối với thông báo này
- Tiêu đề
- Biến không đổi:
- Danh sách các thực thể
Action
phải bao gồm các hành động có giá trị nhận dạng duy nhất - Danh sách thực thể
Action
phải chứa một hoặc hai phần tửAction
. Nếu khả năng thao tác không phải làISSUE_ACTIONABILITY_MANUAL
, thì bạn được phép cóAction
bằng 0. PendingIntent
OnDismiss không được mở một thực thểActivity
- Các yêu cầu bổ sung do cấu hình API đặt ra
- Danh sách các thực thể
Dữ liệu được cung cấp cho Trung tâm an toàn theo một số sự kiện nhất định, vì vậy, bạn cần phải chỉ định nguyên nhân khiến nguồn cung cấp SafetySourceData
bằng một thực thể SafetyEvent
.
SafetyEvent
- Loại bắt buộc, phải là một trong các loại sau:
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ín hiệu này thay vìSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
để 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ếtSafetySourceIssue.Action
ngay trên màn hình Trung tâm an toàn; hãy sử dụng phương thức này thay vìSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
để Trung tâm an toàn có thể theo dõiSafetySourceIssue.Action
đang được giải quyết.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
: Chúng tôi đã cố gắng giải quyếtSafetySourceIssue.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 thuộc tính này thay vìSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
để Trung tâm an toàn có thể theo dõiSafetySourceIssue.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 văn bản của dữ liệu được cung cấp; ngôn ngữ này được phép sử dụngSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
cho việc này.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
: Chúng tôi cung cấp dữ liệu này trong quá trình khởi động ban đầu vì dữ liệu của Trung tâm an toàn không được duy trì sau các lần khởi động lại; bạn được phép sử dụngSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
cho việc này.
- Giá trị nhận dạng
String
không bắt buộc cho mã thông báo truyền tải làm mới. - Giá trị nhận dạng
String
không bắt buộc cho thực thểSafetySourceIssue
đang được giải quyết. - Giá trị nhận dạng
String
không bắt buộc cho thực thểSafetySourceIssue.Action
đang được phân giải. - Bất biến:
- Bạn phải cung cấp mã nhận dạng truyền tin làm mới nếu thuộc loại là
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
- Bạn phải cung cấp mã vấn đề và mã thao tác nếu thuộc loại là
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
hoặcSAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
- Bạn phải cung cấp mã nhận dạng truyền tin làm mới nếu thuộc loại là
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, nguồn đó cung cấp một mục nhập có một thẻ cảnh báo duy nhất):
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 được cung cấp gần đây nhất
Bạn có thể tải dữ liệu mới nhất được cung cấp đến 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 dữ liệu 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. Việc này cũng hữu ích khi kiểm thử.
Sử dụng mã này để tải dữ liệu được cung cấp gần đây nhất 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ẽ chuyển mục nhập sang màu xám, xoá dữ liệu đã lưu vào bộ nhớ đệm và cung cấp một thông báo tương tự như Không thể kiểm tra chế độ cài đặt. Bạn cũng có thể báo cáo lỗi nếu một thực thể của SafetySourceIssue.Action
không thể phân giải, trong trường hợp này, dữ liệu được lưu vào bộ nhớ đệm sẽ không bị xoá và mục nhập giao diện người dùng sẽ không thay đổi; nhưng một thông báo sẽ xuất hiện cho người dùng để cho họ biết rằng có gì đó không ổn.
Bạn có thể đưa ra lỗi bằng cách sử dụng SafetySourceErrorDetails
, bao gồm:
SafetySourceErrorDetails
: Bản sao bắt buộcSafetyEvent
:
// 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);
Phản hồ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ọ nhấn vào nút quét.
Bạn có thể thực hiện việc này bằng cách nhận thông báo truyền tin với thao tác 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 đang 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
- Ý định được bảo vệ mà chỉ hệ thống mới có thể gửi
- Được gửi đến tất cả các nguồn an toàn trong tệp cấu hình dưới dạng một ý định rõ ràng và yêu cầu quyền
SEND_SAFETY_CENTER_UPDATE
- Giá trị chuỗi:
Các thông tin bổ sung sau đây được cung cấp trong 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
- Loại mảng chuỗi (
String[]
), đại diện cho mã nguồn cần làm mới cho ứng dụng nhất định
- Giá trị chuỗi:
EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Giá trị chuỗi:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Loại số nguyên, đại diện cho loại yêu cầu
@IntDef
- Phải là một trong các trạng thái sau:
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
: Yêu cầu nguồn cung cấp dữ liệu tương đối nhanh, thường là khi người dùng mở trangEXTRA_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
- Giá trị chuỗ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 giá trị nhận dạng duy nhất cho lượt làm mới được yêu cầu
- Giá trị chuỗi:
Để nhận tín hiệu từ Trung tâm an toàn, hãy triển khai một thực thể BroadcastReceiver
. Thông báo truyền tin được gửi bằng BroadcastOptions
đặc biệt cho phép bộ thu bắt đầu một dịch vụ trên nền trước.
BroadcastReceiver
phản hồi 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;
}
}
Cùng một thực thể 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>
Tốt nhất là bạn nên triển khai nguồn Trung tâm bảo mật theo cách gọi SafetyCenterManager
khi dữ liệu của nguồn đó thay đổi. Vì lý do liên quan đến tình trạng hệ thống, bạn nên chỉ 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 bảo mật. Nếu cần chức năng này, bạn phải đặt trường refreshOnPageOpenAllowed="true"
trong tệp cấu hình để nguồn nhận được thông báo truyền tin được phân phối trong những trường hợp này.
Phản hồi Trung tâm an toàn khi bật hoặc tắt
Bạn có thể phản hồi khi Trung tâm an toàn được bật hoặc tắt bằng cách sử dụng thao tác 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 khi thiết bị đang chạy
- Không được gọi khi khởi động (hãy sử dụng
ACTION_BOOT_COMPLETED
để làm việc đó) - Ý định được bảo vệ mà chỉ hệ thống mới có thể gửi
- Được gửi đến tất cả nguồn an toàn trong tệp cấu hình dưới dạng một ý định rõ ràng, yêu cầu quyền
SEND_SAFETY_CENTER_UPDATE
- Được gửi dưới dạng ý định ngầm ẩn yêu cầu quyền
READ_SAFETY_CENTER_STATUS
- Giá trị chuỗi:
Thao tác theo ý định này rất hữu ích khi 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ị.
Triển khai các hành động giải quyết
Thao tác giải quyết là một thực thể SafetySourceIssue.Action
mà người dùng có thể giải quyết ngay trên màn hình Trung tâm an toàn. Người dùng nhấn vào một nút hành động và thực thể PendingIntent
trên SafetySourceIssue.Action
do nguồn an toàn gửi sẽ được kích hoạt. Thao tác này sẽ giải quyết sự cố ở chế độ nền và thông báo cho Trung tâm an toàn khi hoạt động xong.
Để triển khai các thao tác giải quyết, nguồn của Trung tâm an toàn có thể sử dụng một dịch vụ nếu thao tác này dự kiến mất một chút thời gian (PendingIntent.getService
) hoặc một broadcast receiver (PendingIntent.getBroadcast
).
Sử dụng mã này để gửi sự cố đang được giải quyết tới 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
sẽ 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).
}
}
Cùng một thực thể 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>
Phản hồi các trường hợp loại bỏ vấn đề
Bạn có thể chỉ định một thực thể PendingIntent
có thể được kích hoạt khi một thực thể SafetySourceIssue
bị đóng. Trung tâm an toàn xử lý các trường hợp đóng vấn đề sau:
- Nếu một nguồn đẩy ra một sự cố, người dùng có thể đóng sự cố đó trên màn hình Trung tâm an toàn bằng cách nhấn vào nút đóng (nút X trên thẻ cảnh báo).
- Khi người dùng loại bỏ một vấn đề, nếu vấn đề đó vẫn tiếp diễn, vấn đề đó sẽ không xuất hiện lại trong giao diện người dùng.
- Các chế độ đóng 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 một vấn đề rồi cung cấp lại vấn đề đó sau này, thì vấn đề đó sẽ xuất hiện trở lại. Điều này cho phép người dùng thấy một cảnh báo, loại bỏ rồi thực hiện hành động nhằm giảm nhẹ vấn đề nhưng sau đó người dùng lại làm lại điều gì đó gây ra vấn đề tương tự. Lúc này, thẻ cảnh báo sẽ xuất hiện lại.
- Thẻ cảnh báo màu vàng và màu đỏ sẽ xuất hiện lại sau mỗi 180 ngày trừ phi người dùng đóng thẻ nhiều lần.
Nguồn không cần phải có hành vi bổ sung trừ phi:
- Nguồn sẽ cố gắng triển khai hành vi này theo cách khác, chẳng hạn như không bao giờ xuất hiện lại vấn đề.
- Nguồn cố gắng sử dụng giá trị này làm 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ơ
Bạn có thể sử dụng API SafetyCenterManager
trên nhiều người dùng và hồ sơ. Để biết thêm thông tin, hãy xem bài viết Tạo ứ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 thực thể UserHandle
, vì vậy, thực thể SafetyCenterManager
được trả về sẽ tương tác với Trung tâm an toàn của thực thể UserHandle
đó. Theo mặc định, Context
được liên kết với người dùng đang chạy, nhưng bạn có thể tạo một thực thể cho một người dùng khác nếu ứng dụng có các quyền INTERACT_ACROSS_USERS
và INTERACT_ACROSS_USERS_FULL
. Ví dụ này cho thấy việc thực hiện lệnh gọi trên nhiều 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 riêng cho từng người dùng, nhưng hợp nhất dữ liệu của tất cả các hồ sơ được quản lý liên kết với một người dùng nhất định.
Khi bạn đặt profile="all_profiles"
cho nguồn trong tệp cấu hình, những trường hợp 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ơ mẹ) và tất cả hồ sơ được quản lý liên kết với người dùng đó (sử dụng các thực thể
titleForWork
). Tín hiệu làm mới hoặc quét lại sẽ được gửi đến hồ sơ gốc và tất cả hồ sơ được quản lý liên kết. Trình thu nhận liên kết được khởi động cho từng hồ sơ và có thể cung cấp dữ liệu được liên kết trực tiếp cho
SafetyCenterManager
mà không phải thực hiện lệnh gọi giữa nhiều hồ sơ, trừ trường hợp trình thu nhận hoặc ứng dụng làsingleUser
.Nguồn này 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ý. Dữ liệu cho mỗi mục nhập giao diện người dùng có thể khác nhau tuỳ thuộc vào hồ sơ.
Thử nghiệm
bạn có thể truy cập vào ShadowSafetyCenterManager
và sử dụng công cụ này trong chương trình kiểm thử 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 thêm các kiểm thử toàn diện (E2E), nhưng điều này 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 chương trình kiểm thử E2E này, hãy xem phần kiểm thử CTS (CtsSafetyCenterTestCases)
API kiểm thử và API nội bộ
API nội bộ và API kiểm thử dùng cho mục đích nội bộ nên không được mô tả chi tiết trong hướng dẫn này. Tuy nhiên, trong tương lai, chúng tôi có thể mở rộng một số API nội bộ để cho phép OEM xây dựng giao diện người dùng của riêng họ. Chúng tôi sẽ cập nhật hướng dẫn này để hướng dẫn cách sử dụng các API đó.
Quyền
MANAGE_SAFETY_CENTER
internal|installer|role
- Dùng cho các API Trung tâm an toàn nội bộ
- Chỉ cấp cho PermissionController và shell
Ứng dụng Cài đặt
Chuyển hướng đến Trung tâm an toàn
Theo mặc định, người dùng có thể truy cập Trung tâm an toàn thông qua ứng dụng Cài đặt bằng một mục mới là Bảo mật và quyền riêng tư. Nếu dùng một ứng dụng Cài đặt khác hoặc nếu đã sửa đổi ứng dụng Cài đặt, bạn có thể phải tuỳ chỉnh cách truy cập vào Trung tâm an toàn.
Khi Trung tâm an toàn được bật:
- Mục Quyền riêng tư cũ bị ẩn mã
- Mục nhập Bảo mật cũ bị ẩn mã
- Thêm mục Bảo mật và quyền riêng tư mới mã
- Mục Bảo mật và quyền riêng tư mới chuyển hướng đến mã của Trung tâm an toàn
- Các thao tác theo ý định
android.settings.PRIVACY_SETTINGS
vàandroid.settings.SECURITY_SETTINGS
được chuyển hướng đến mở Trung tâm an toàn (mã: bảo mật, quyền riêng tư)
Các trang bảo mật và quyền riêng tư nâng cao
Ứng dụng Cài đặt có các chế độ cài đặt khác trong phần Các chế độ cài đặt bảo mật khác và Các chế độ cài đặt quyền riêng tư khác trong Trung tâm an toàn:
Mã bảo mật nâng cao
Mã quyền riêng tư nâng cao
Kể từ Android 14, trang cài đặt bảo mật và quyền riêng tư nâng cao sẽ được hợp nhất trong một trang "Bảo mật và quyền riêng tư khác" duy nhất bằng thao tác theo ý định
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
Nguồn an toàn
Trung tâm an toàn tích hợp với một bộ nguồn an toàn cụ thể do ứng dụng cài đặt cung cấp:
- Nguồn an toàn trên màn hình khoá sẽ xác minh rằng màn hình khoá được thiết lập bằng mật mã (hoặc phương thức bảo mật khác), nhằm đảm bảo thông tin riêng tư của người dùng được bảo vệ khỏi quyền truy cập từ bên ngoài.
- Một nguồn an toàn sinh trắc học (ẩn theo mặc định) xuất hiện để 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 này trong Trung tâm an toàn thông qua tính năng tìm kiếm mã Android. Nếu ứng dụng Cài đặt không được sửa đổi (tên gói, mã nguồn hoặc mã nguồn xử lý màn hình khoá và hệ thống nhận dạng sinh trắc học không thay đổi), thì quá trình tích hợp này sẽ thành công. Nếu không, bạn có thể 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ư quá trình tích hợp. Để biết thêm thông tin, hãy xem phần Cập nhật tệp cấu hình và chế độ cài đặt tích hợp.
Giới thiệu về PendingIntent
Nếu bạn dựa vào tính năng tích hợp hiện có của ứng dụng Cài đặt trong Trung tâm an toàn trong Android 14 trở lên, thì lỗi mô tả bên dưới đã được khắc phục. Trong trường hợp này, bạn không cần đọc phần 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 trong Trung tâm an toàn.
Giải pháp cho PendingIntent
Lỗi này là do ứng dụng Cài đặt sử dụng tiện ích thực thể Intent
để xác định mảnh cần mở. Vì Intent#equals
không tính đến thông tin bổ sung về thực thể Intent
, nên thực thể PendingIntent
cho biểu tượng trình đơn 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 nhằm mục đích điều hướng đến một giao diện người dùng khác). Vấn đề này được khắc phục trong một bản phát hành QPR bằng cách phân biệt các thực thể PendingIntent
theo mã yêu cầu. Ngoài ra, bạn có thể phân biệt giá trị này 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ốngPermissionController bên trong mô-đun PermissionsController. Các nguồn này hoạt động giống như các nguồn thông thường trong Trung tâm an toàn và không được xử lý đặc biệt. Mã cho các nguồn này có sẵn thông qua tính năng 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ụ:
- Hỗ trợ tiếp cận
- Tự động thu hồi quyền đối với các ứng dụng không dùng đến
- Quyền truy cập thông tin vị trí
- Trình xử lý thông báo
- Thông tin về chính sách cơ quan