Przekierowanie do Centrum bezpieczeństwa
Każda aplikacja może otworzyć Centrum bezpieczeństwa za pomocą działania android.content.Intent.ACTION_SAFETY_CENTER
(wartość ciągu tekstowego android.intent.action.SAFETY_CENTER
).
Aby otworzyć Centrum bezpieczeństwa, zadzwoń z instancji Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
Przekierowanie do konkretnego problemu
Można też przekierowywać użytkowników do konkretnej karty ostrzeżenia w Centrum bezpieczeństwa za pomocą określonych dodatków do intencji. Te dodatkowe funkcje nie są przeznaczone do użytku przez osoby trzecie, dlatego są częścią SafetyCenterManager
, która jest częścią @SystemApi
. Dostęp do tych funkcji mają tylko aplikacje systemowe.
Elementy dodatkowe intencji, które przekierowują do konkretnej karty ostrzeżenia:
EXTRA_SAFETY_SOURCE_ID
- Wartość ciągu znaków:
android.safetycenter.extra.SAFETY_SOURCE_ID
- Typ ciągu znaków: określa identyfikator źródła bezpieczeństwa powiązanej karty ostrzeżenia.
- Wymagane, aby przekierowanie do problemu działało.
- Wartość ciągu znaków:
EXTRA_SAFETY_SOURCE_ISSUE_ID
- Wartość ciągu znaków:
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- Typ ciągu znaków: określa identyfikator karty ostrzegawczej.
- Wymagane, aby przekierowanie do problemu działało.
- Wartość ciągu znaków:
EXTRA_SAFETY_SOURCE_USER_HANDLE
- Wartość ciągu znaków:
android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
UserHandle
type: określaUserHandle
dla powiązanej karty ostrzeżenia.- Opcjonalne (domyślnie bieżący użytkownik)
- Wartość ciągu znaków:
W ramach instancji Activity
można użyć poniższego fragmentu kodu, aby otworzyć ekran Centrum bezpieczeństwa dla konkretnego problemu:
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);
przekierowanie na konkretną podstronę (od Androida 14),
W Androidzie 14 lub nowszym strona Centrum bezpieczeństwa jest podzielona na kilka podstron, które reprezentują różne SafetySourcesGroup
(w Androidzie 13 są one wyświetlane jako elementy z możliwością zwijania).
Za pomocą tego dodatku możesz przekierować użytkowników na konkretną podstronę:
EXTRA_SAFETY_SOURCES_GROUP_ID
- Wartość ciągu znaków:
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- Typ ciąg znaków: określa identyfikator
SafetySourcesGroup
. - Wymagane, aby przekierowanie do podstrony działało.
- Wartość ciągu znaków:
Ten fragment kodu możesz użyć w instancji Activity
, aby otworzyć ekran Centrum bezpieczeństwa na konkretnej podstronie:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");
startActivity(openSafetyCenterIntent);
Korzystanie z interfejsów API źródłowych Centrum bezpieczeństwa
Interfejsy API źródłowe Safety Center są dostępne za pomocą interfejsu SafetyCenterManager
(który jest interfejsem @SystemApi
). Kod interfejsu API jest dostępny w wyszukiwarce kodu.
Kod implementacji interfejsów API jest dostępny w wyszukiwarce kodu.
Uprawnienia
Interfejsy API źródła Centrum bezpieczeństwa są dostępne tylko dla aplikacji systemowych z listy dozwolonych, które mają uprawnienia wymienione poniżej. Więcej informacji znajdziesz w artykule Uprawnienia z poziomu uprawnień.
READ_SAFETY_CENTER_STATUS
signature|privileged
- Używany do interfejsu API
SafetyCenterManager#isSafetyCenterEnabled()
(nie jest wymagany w przypadku źródeł Safety Center, które potrzebują tylko uprawnieńSEND_SAFETY_CENTER_UPDATE
) - Używany przez aplikacje systemowe, które sprawdzają, czy Centrum bezpieczeństwa jest włączone
- przyznawane tylko aplikacjom systemowym z listy dozwolonych;
SEND_SAFETY_CENTER_UPDATE
internal|privileged
- Używany do włączonego interfejsu API i interfejsu API źródeł bezpieczeństwa
- Używane tylko przez źródła bezpieczeństwa
- przyznawane tylko aplikacjom systemowym z listy dozwolonych;
Te uprawnienia są uprawnieniami uprzywilejowanymi i można je uzyskać tylko przez dodanie ich do odpowiedniego pliku, na przykład pliku com.android.settings.xml
aplikacji Ustawienia i pliku AndroidManifest.xml
aplikacji. Więcej informacji o modelu uprawnień znajdziesz w artykule protectionLevel
.
Pobieranie SafetyCenterManager
SafetyCenterManager
to klasa @SystemApi
, która jest dostępna w aplikacjach systemowych od Androida 13. Ten wywołanie pokazuje, jak uzyskać obiekt 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;
}
Sprawdzanie, czy Centrum bezpieczeństwa jest włączone
Ta wywołania sprawdza, czy Centrum bezpieczeństwa jest włączone. Wywołanie wymaga uprawnienia READ_SAFETY_CENTER_STATUS
lub SEND_SAFETY_CENTER_UPDATE
:
boolean isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled();
if (isSafetyCenterEnabled) {
// …
} else {
// …
}
Przekazywanie danych
Dane źródłowe Centrum bezpieczeństwa z podanym String sourceId
są przekazywane do Centrum bezpieczeństwa za pomocą obiektu SafetySourceData
, który reprezentuje wpis interfejsu użytkownika i listę problemów (karty z ostrzeżeniem). Element interfejsu i karty ostrzegawcze mogą mieć różne poziomy ważności określone w klasie SafetySourceData
:
SEVERITY_LEVEL_UNSPECIFIED
- Nie określono poziomu ważności
- Kolor: szary lub przezroczysty (w zależności od
SafetySourcesGroup
pozycji) - Służy do danych dynamicznych, które są wyświetlane jako wpisy statyczne w interfejsie lub do wyświetlania nieokreślonego wpisu.
- Nie można ich używać w przypadku kart z ostrzeżeniem.
SEVERITY_LEVEL_INFORMATION
- podstawowe informacje lub drobne sugestie,
- Kolor: zielony
SEVERITY_LEVEL_RECOMMENDATION
- zalecenie, aby użytkownik podjął działania w sprawie tego problemu, ponieważ może on stanowić zagrożenie;
- Kolor: żółty
SEVERITY_LEVEL_CRITICAL_WARNING
- ostrzeżenie o krytycznym problemie, który wymaga od użytkownika podjęcia działań, ponieważ stwarza ono ryzyko;
- Kolor: czerwony
SafetySourceData
Obiekt SafetySourceData
składa się z elementu interfejsu, kart z ostrzeżeniem i invariantów.
- Opcjonalny przykład
SafetySourceStatus
(element interfejsu użytkownika) - Lista wystąpień (kart)
SafetySourceIssue
- Opcjonalne
Bundle
dodatki (od wersji 14) - Niezmienniki:
- Lista
SafetySourceIssue
musi składać się z problemów o unikalnych identyfikatorach. - Instancja
SafetySourceIssue
nie może mieć większego znaczenia niżSafetySourceStatus
, jeśli taka istnieje (chyba żeSafetySourceStatus
toSEVERITY_LEVEL_UNSPECIFIED
, w którym przypadku dozwolone są problemySEVERITY_LEVEL_INFORMATION
). - Należy spełnić dodatkowe wymagania narzucone przez konfigurację interfejsu API. Jeśli na przykład źródło jest przeznaczone tylko do rozwiązywania problemów, nie może ono udostępniać instancji
SafetySourceStatus
.
- Lista
SafetySourceStatus
- Wymagany
CharSequence
tytuł - Wymagany
CharSequence
podsumowanie - Wymagany poziom ważności
- Opcjonalny
PendingIntent
: instancja przekierowująca użytkownika na odpowiednią stronę (domyślnie używana jest instancjaintentAction
z konfiguracji, jeśli taka istnieje) - Opcjonalnie
IconAction
(wyświetlany jako ikona obok wpisu) składający się z:- Wymagany typ ikony:
ICON_TYPE_GEAR
: widoczne jako kółko obok wpisu w interfejsieICON_TYPE_INFO
: wyświetlana jako ikona informacji obok wpisu w interfejsie
- Wymagane
PendingIntent
do przekierowania użytkownika na inną stronę
- Wymagany typ ikony:
- Opcjonalna wartość logiczna
enabled
, która umożliwia oznaczenie elementu interfejsu jako wyłączonego, aby nie można było go kliknąć (wartość domyślna totrue
). - Niezmienniki:
- Instancje
PendingIntent
muszą otwierać instancjęActivity
. - Jeśli wpis jest wyłączony, musi być oznaczony jako
SEVERITY_LEVEL_UNSPECIFIED
. - dodatkowe wymagania narzucone przez konfigurację interfejsu API;
- Instancje
SafetySourceIssue
- Wymagany unikalny identyfikator
String
- Wymagany
CharSequence
tytuł - Opcjonalny
CharSequence
- Wymagany
CharSequence
podsumowanie - Wymagany poziom ważności
- Opcjonalna kategoria problemu, która musi być jedną z tych kategorii:
ISSUE_CATEGORY_DEVICE
: problem dotyczy urządzenia użytkownika.ISSUE_CATEGORY_ACCOUNT
: problem dotyczy kont użytkownika.ISSUE_CATEGORY_GENERAL
: problem dotyczy ogólnego bezpieczeństwa użytkownika. Jest to ustawienie domyślne.ISSUE_CATEGORY_DATA
(od Androida 14): Ten problem wpływa na dane użytkownika.ISSUE_CATEGORY_PASSWORDS
(Od Androida 14): problem dotyczy haseł użytkownika.ISSUE_CATEGORY_PERSONAL_SAFETY
(od wersji Androida 14): problem dotyczy osobistego bezpieczeństwa użytkownika.
- Lista elementów
Action
, które użytkownik może wykonać w przypadku tego problemu. Każdy elementAction
składa się z:- Wymagany unikalny identyfikator
String
- Wymagana etykieta
CharSequence
- Wymagane
PendingIntent
do przekierowania użytkownika na inną stronę lub przetworzenia działania bezpośrednio na ekranie Centrum bezpieczeństwa. - Opcjonalna wartość logiczna określająca, czy ten problem można rozwiązać bezpośrednio na ekranie Centrum bezpieczeństwa (wartość domyślna to
false
). - Opcjonalny
CharSequence
komunikat o pomyślnym rozwiązaniu problemu, który wyświetla się użytkownikowi, gdy problem zostanie rozwiązany bezpośrednio na ekranie Centrum bezpieczeństwa
- Wymagany unikalny identyfikator
- Opcjonalna funkcja
PendingIntent
, która jest wywoływana, gdy użytkownik zamknie problem (domyślnie nie jest wywoływana żadna funkcja). - Wymagany identyfikator typu problemu
String
; jest podobny do identyfikatora problemu, ale nie musi być unikalny i jest używany do rejestrowania - Opcjonalnie
String
dla identyfikatora deduplikacji. Umożliwia to publikowanie tego samegoSafetySourceIssue
z różnych źródeł i wyświetlanie go tylko raz w interfejsie użytkownika, o ile ma on ten sam identyfikatordeduplicationGroup
(od Androida 14). Jeśli nie podasz tej wartości, problem nigdy nie zostanie odduplikowany. - Opcjonalnie
CharSequence
dla tytułu informacji o pochodzeniu. Jest to tekst, który wskazuje, skąd pochodzi karta z ostrzeżeniem (od Androida 14). Jeśli nie określono inaczej, używany jest tytułSafetySourcesGroup
- Opcjonalna możliwość działania w przypadku problemu (od Androida 14), która musi być jedną z tych opcji:
ISSUE_ACTIONABILITY_MANUAL
: użytkownik musi rozwiązać ten problem ręcznie. Jest to ustawienie domyślne.ISSUE_ACTIONABILITY_TIP
: ten problem jest tylko wskazówką i nie wymaga podania przez użytkownika żadnych danych.ISSUE_ACTIONABILITY_AUTOMATIC
: to zgłoszenie zostało już rozpatrzone i być może nie wymaga żadnych działań ze strony użytkownika.
- Opcjonalne zachowanie powiadomienia (od Androida 14), które musi być jednym z tych:
NOTIFICATION_BEHAVIOR_UNSPECIFIED
: Centrum bezpieczeństwa zdecyduje, czy powiadomienie jest potrzebne do wyświetlenia karty ostrzegawczej. Jest to ustawienie domyślne.NOTIFICATION_BEHAVIOR_NEVER
: nie jest publikowane żadne powiadomienie.NOTIFICATION_BEHAVIOR_DELAYED
: powiadomienie jest publikowane po pewnym czasie od zgłoszenia problemu.NOTIFICATION_BEHAVIOR_IMMEDIATELY
: powiadomienie jest publikowane natychmiast po zgłoszeniu problemu.
- Opcjonalnie
Notification
, aby wyświetlić powiadomienie niestandardowe z kartą ostrzegawczą (od Androida 14). Jeśli nie podasz żadnej wartości,Notification
zostanie utworzona na podstawie karty z ostrzeżeniem. Skład:- Wymagany
CharSequence
tytuł - Wymagany
CharSequence
podsumowanie - Lista elementów
Action
, które użytkownik może wykonać w przypadku tego powiadomienia
- Wymagany
- Niezmienniki:
- Lista instancji
Action
musi składać się z działań o unikalnych identyfikatorach. - Lista instancji
Action
musi zawierać co najmniej 1 lub 2 elementyAction
. Jeśli możliwość działania nie jestISSUE_ACTIONABILITY_MANUAL
, można ustawić wartośćAction
równą 0. - Obsługa OnDismiss
PendingIntent
nie może otwierać instancjiActivity
. - Dodatkowe wymagania narzucone przez konfigurację interfejsu API
- Lista instancji
Dane są przekazywane do Centrum Bezpieczeństwa po wystąpieniu określonych zdarzeń, dlatego należy określić, co spowodowało, że źródło przekazało SafetySourceData
wystąpienie SafetyEvent
.
SafetyEvent
- Wymagany typ, który musi być jednym z tych typów:
SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
: stan źródła uległ zmianie.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
: odpowiadanie na sygnał od Centrum bezpieczeństwa dotyczący odświeżenia lub ponownego skanowania; użyj tego polecenia zamiastSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
, aby Centrum bezpieczeństwa mogło śledzić prośbę o odświeżenie lub ponowne skanowanie.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
: rozwiązaliśmy problemSafetySourceIssue.Action
bezpośrednio na ekranie Centrum bezpieczeństwa. ZamiastSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
użyj tej opcji, aby Centrum bezpieczeństwa mogło śledzić rozwiązanie problemuSafetySourceIssue.Action
.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
: próbowaliśmy rozwiązać problemSafetySourceIssue.Action
bezpośrednio na ekranie Centrum bezpieczeństwa, ale się nie udało. Zamiast opcjiSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
użyj opcjiSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
, aby Centrum bezpieczeństwa mogło śledzić problemSafetySourceIssue.Action
.SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED
: język urządzenia uległ zmianie, dlatego aktualizujemy tekst podanych danych. Do tego celu można użyćSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
: te dane są udostępniane podczas uruchamiania urządzenia, ponieważ dane Centrum bezpieczeństwa nie są zachowywane po ponownym uruchomieniu. Do tego celu można użyćSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
.
- Opcjonalny identyfikator
String
dla identyfikatora transmisji odświeżania. - Opcjonalny identyfikator
String
instancjiSafetySourceIssue
, która została rozwiązana. - Opcjonalny identyfikator
String
instancjiSafetySourceIssue.Action
, która jest rozwiązywana. - Niezmienniki:
- Jeśli typ to
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
, musisz podać identyfikator transmisji odświeżania. - Musisz podać identyfikatory problemu i działania, jeśli ich typ to
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
lubSAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
.
- Jeśli typ to
Poniżej przedstawiamy przykład tego, jak źródło może przekazywać dane do Centrum bezpieczeństwa (w tym przypadku jest to wpis z jedną kartą ostrzegawczą):
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);
Pobieranie ostatnich danych
Możesz pobrać ostatnie dane przesłane do Centrum Bezpieczeństwa dla źródła należącego do Twojej aplikacji. Możesz to wykorzystać, aby wyświetlić coś w interfejsie, sprawdzić, czy dane wymagają aktualizacji przed wykonaniem kosztownej operacji, lub przesłać do Centrum Bezpieczeństwa tę samą instancję SafetySourceData
z niektórymi zmianami lub nową instancję SafetyEvent
. Jest też przydatny podczas testowania.
Użyj tego kodu, aby uzyskać ostatnie dane przesłane do Centrum bezpieczeństwa:
SafetySourceData lastDataProvided =
safetyCenterManager.getSafetySourceData("MySourceId");
Zgłaszanie błędu
Jeśli nie możesz zebrać danych SafetySourceData
, możesz zgłosić błąd do Centrum bezpieczeństwa. Spowoduje to zaznaczenie wpisu na szaro, wyczyszczenie danych z poziomu pamięci podręcznej i wyświetlenie komunikatu podobnego do Nie udało się sprawdzić ustawień. Możesz też zgłosić błąd, jeśli instancja SafetySourceIssue.Action
nie zostanie rozwiązana. W takim przypadku dane w pamięci podręcznej nie zostaną usunięte, a element w interfejsie nie zmieni się, ale użytkownik otrzyma wiadomość z informacją, że coś poszło nie tak.
Błąd możesz podać za pomocą elementu SafetySourceErrorDetails
, który składa się z:
SafetySourceErrorDetails
: wymaganySafetyEvent
:
// 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);
Odpowiedź na prośbę o odświeżenie lub ponowne zeskanowanie
Możesz otrzymać sygnał z Centrum bezpieczeństwa, aby podać nowe dane. Odpowiedź na żądanie odświeżenia lub ponownego skanowania zapewnia, że użytkownik zobaczy aktualny stan po otwarciu Centrum bezpieczeństwa i kliknięciu przycisku skanowania.
Aby to zrobić, musisz otrzymać transmisję z tymi działaniami:
ACTION_REFRESH_SAFETY_SOURCES
- Wartość ciągu znaków:
android.safetycenter.action.REFRESH_SAFETY_SOURCES
- Wywoływane, gdy Centrum bezpieczeństwa wysyła żądanie odświeżenia danych źródła bezpieczeństwa w przypadku danej aplikacji.
- Chroniony zamiar, który może być wysyłany tylko przez system
- Wysyłane do wszystkich źródeł zabezpieczeń w pliku konfiguracji jako jawne intencje i wymagające uprawnienia
SEND_SAFETY_CENTER_UPDATE
- Wartość ciągu znaków:
W ramach tej transmisji dostępne są te dodatkowe materiały:
EXTRA_REFRESH_SAFETY_SOURCE_IDS
- Wartość ciągu znaków:
android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
- Typ tablicy ciągów znaków (
String[]
), który reprezentuje identyfikatory źródeł do odświeżenia w danej aplikacji.
- Wartość ciągu znaków:
EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Wartość ciągu znaków:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Typ liczba całkowita, który reprezentuje typ żądania
@IntDef
- Musi to być jeden z tych elementów:
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
: żądanie przesłania danych przez źródło w względnie krótkim czasie, zwykle po otwarciu strony przez użytkownika.EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA
: żądanie, aby źródło dostarczyło jak najświeższe dane, zwykle gdy użytkownik naciśnie przycisk ponownego skanowania.
- Wartość ciągu znaków:
EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Wartość ciągu znaków:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Typ string, reprezentuje unikalny identyfikator żądanego odświeżenia
- Wartość ciągu znaków:
Aby otrzymać sygnał z Centrum bezpieczeństwa, zaimplementuj instancję BroadcastReceiver
. Transmisja jest wysyłana ze specjalnym BroadcastOptions
, który umożliwia odbiornikowi uruchomienie usługi na pierwszym planie.
BroadcastReceiver
odpowiada na prośbę o odświeżenie:
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;
}
}
W przykładzie powyżej ta sama instancja BroadcastReceiver
jest zadeklarowana w funkcji 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>
W idealnej sytuacji źródło Centrum bezpieczeństwa jest zaimplementowane w taki sposób, że wywołuje funkcję SafetyCenterManager
, gdy zmieniają się jego dane. Ze względu na stabilność systemu zalecamy reagowanie tylko na sygnał ponownego skanowania (gdy użytkownik kliknie przycisk skanowania), a nie na otwarcie Centrum bezpieczeństwa. Jeśli ta funkcja jest wymagana, w źródle należy ustawić pole refreshOnPageOpenAllowed="true"
w pliku konfiguracji, aby mogło ono odbierać transmisję w takich przypadkach.
Odpowiedź na Centrum bezpieczeństwa po włączeniu lub wyłączeniu
Możesz odpowiedzieć na to, czy Centrum bezpieczeństwa jest włączone czy wyłączone, używając tej czynności:
ACTION_SAFETY_CENTER_ENABLED_CHANGED
- Wartość ciągu znaków:
android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
- Wywoływany, gdy Centrum bezpieczeństwa jest włączone lub wyłączone, a urządzenie jest włączone.
- Nie jest wywoływany podczas uruchamiania (użyj do tego funkcji
ACTION_BOOT_COMPLETED
). - Chroniony zamiar, który może być wysyłany tylko przez system
- Wysyłane do wszystkich źródeł zabezpieczeń w pliku konfiguracyjnym jako jawne intencje. Wymaga uprawnienia
SEND_SAFETY_CENTER_UPDATE
- Wysłane jako niejawny zamiar, który wymaga uprawnienia
READ_SAFETY_CENTER_STATUS
- Wartość ciągu znaków:
To działanie jest przydatne do włączania i wyłączania funkcji związanych z Centrum bezpieczeństwa na urządzeniu.
Wdrażanie działań naprawczych
Rozwiązywanie to działanie dotyczące SafetySourceIssue.Action
, które użytkownik może wykonać bezpośrednio na ekranie Centrum bezpieczeństwa. Użytkownik klika przycisk polecenia, a następnie uruchamia się instancja PendingIntent
na SafetySourceIssue.Action
przesłana przez źródło bezpieczeństwa. Rozwiązuje ona problem w tle i powiadamia Centrum bezpieczeństwa po zakończeniu działania.
Aby wdrożyć działania rozwiązujące, źródło Centrum bezpieczeństwa może użyć usługi, jeśli operacja ma potrwać pewien czas (PendingIntent.getService
), lub odbiornika transmisji (PendingIntent.getBroadcast
).
Aby wysłać do Centrum bezpieczeństwa problem, który został rozwiązany, użyj tego kodu:
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
rozwiązuje problem:
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).
}
}
W przykładzie powyżej ta sama instancja BroadcastReceiver
jest zadeklarowana w funkcji 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>
Odpowiadanie na odrzucenie zgłoszenia
Możesz określić instancję PendingIntent
, która może zostać uruchomiona po odrzuceniu instancji SafetySourceIssue
. Centrum bezpieczeństwa obsługuje te problemy:
- Jeśli źródło przesyła problem, użytkownik może go zamknąć na ekranie Centrum bezpieczeństwa, klikając przycisk zamknięcia (przycisk X na karcie ostrzeżenia).
- Jeśli użytkownik zamknie problem, ale ten nadal występuje, nie będzie on ponownie wyświetlany w interfejsie.
- Trwałe zamknięcia na dysku pozostają po ponownym uruchomieniu urządzenia.
- Jeśli źródło w Centrum bezpieczeństwa przestanie przekazywać problem, a potem znowu zacznie, problem powróci. Ma to na celu umożliwienie łagodzenia sytuacji, w której użytkownik widzi ostrzeżenie, odrzuca je, a następnie podejmuje działanie, które powinno rozwiązać problem, ale potem ponownie robi coś, co powoduje podobny problem. W tym momencie karta z ostrzeżeniem powinna się ponownie wyświetlić.
- Żółte i czerwone karty z ostrzeżeniem pojawiają się co 180 dni, chyba że użytkownik odrzuci je kilka razy.
Źródło nie powinno wymagać dodatkowych zachowań, chyba że:
- Źródło próbuje wdrożyć to zachowanie w inny sposób, np. nigdy nie ujawnia problemu.
- Źródło próbuje użyć tego jako wywołania zwrotnego, na przykład do zarejestrowania informacji.
Przesyłanie danych wielu użytkowników/profili
Interfejsu SafetyCenterManager
API można używać w przypadku różnych użytkowników i profili. Więcej informacji znajdziesz w artykule Tworzenie aplikacji obsługujących wielu użytkowników. Obiekt Context
, który udostępnia SafetyCenterManager
, jest powiązany z instancją UserHandle
, więc zwracana instancja SafetyCenterManager
wchodzi w interakcję z Centrum Bezpieczeństwa w przypadku tej instancji UserHandle
. Domyślnie Context
jest powiązana z bieżącym użytkownikiem, ale można utworzyć instancję dla innego użytkownika, jeśli aplikacja ma uprawnienia INTERACT_ACROSS_USERS
i INTERACT_ACROSS_USERS_FULL
. Ten przykład pokazuje nawiązywanie połączenia przez różnych użytkowników/profile:
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
Każdy użytkownik na urządzeniu może mieć kilka profili zarządzanych. Centrum bezpieczeństwa udostępnia różne dane dla każdego użytkownika, ale łączy dane ze wszystkich zarządzanych profili powiązanych z danym użytkownikiem.
Gdy w pliku konfiguracji dla źródła ustawisz wartość profile="all_profiles"
, nastąpi:
- W interfejsie użytkownika (nadrzędny profil) i wszystkich powiązanych z nim profili zarządzanych (które korzystają z instancji
titleForWork
) jest widoczny odpowiedni wpis. Sygnał odświeżania lub ponownego skanowania jest wysyłany do nadrzędnego profilu i wszystkich powiązanych profili zarządzanych. Powiązany odbiornik jest uruchamiany dla każdego profilu i może przekazywać powiązane dane bezpośrednio do
SafetyCenterManager
bez konieczności wywoływania funkcji na różnych profilach, chyba że odbiornik lub aplikacja tosingleUser
.Źródło powinno udostępniać dane o użytkowniku i wszystkich zarządzanych przez niego profilach. Dane w poszczególnych elementach interfejsu mogą się różnić w zależności od profilu.
Testowanie
możesz uzyskać dostęp do ShadowSafetyCenterManager
i użyć go w teście 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);
}
Możesz napisać więcej testów end-to-end (E2E), ale nie jest to tematem tego przewodnika. Więcej informacji o pisaniu testów E2E znajdziesz w artykule Testy CTS (CtsSafetyCenterTestCases).
Interfejsy API testowe i wewnętrzne
Interfejsy API wewnętrzne i testowe są przeznaczone do użytku wewnętrznego, dlatego nie są szczegółowo opisane w tym przewodniku. W przyszłości możemy jednak udostępnić niektóre wewnętrzne interfejsy API, aby umożliwić producentom urządzeń OEM tworzenie własnych interfejsów użytkownika. W tym celu zaktualizujemy ten przewodnik.
Uprawnienia
MANAGE_SAFETY_CENTER
internal|installer|role
- używane do wewnętrznych interfejsów API Centrum Bezpieczeństwa;
- Dozwolone tylko w komponencie PermissionController i w powłoce
Aplikacja Ustawienia
Przekierowanie do Centrum bezpieczeństwa
Domyślnie Centrum bezpieczeństwa jest dostępne w aplikacji Ustawienia w nowej sekcji Bezpieczeństwo i prywatność. Jeśli używasz innej aplikacji Ustawienia lub zmodyfikowałeś aplikację Ustawienia, konieczne może być dostosowanie sposobu otwierania Centrum bezpieczeństwa.
Gdy Centrum bezpieczeństwa jest włączone:
- Starszy wpis Prywatność jest ukryty w pliku kodu.
- Starszy wpis Bezpieczeństwo jest ukryty kod
- Dodano nowy wpis Bezpieczeństwo i prywatność code
- Nowy wpis Bezpieczeństwo i prywatność przekierowuje do kodu Centrum bezpieczeństwa
android.settings.PRIVACY_SETTINGS
iandroid.settings.SECURITY_SETTINGS
działania intencyjne są przekierowywane do Centrum bezpieczeństwa (kod: bezpieczeństwo, prywatność)
Zaawansowane strony dotyczące bezpieczeństwa i prywatności
Aplikacja Ustawienia zawiera dodatkowe ustawienia w sekcjach Więcej ustawień zabezpieczeń i Więcej ustawień prywatności, które są dostępne w Centrum bezpieczeństwa:
Zaawansowany kod zabezpieczeń
Zaawansowany kod prywatności
Od Androida 14 strona zaawansowanych ustawień zabezpieczeń i prywatności została połączona w jedną stronę „Więcej ustawień bezpieczeństwa i prywatności” z działaniem intencją.
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
Źródła bezpieczeństwa
Centrum bezpieczeństwa integruje się z określonym zestawem źródeł bezpieczeństwa udostępnianych przez aplikację Ustawienia:
- Bezpieczeństwo ekranu blokady: źródło weryfikujące, czy ekran blokady jest chroniony kodem dostępu (lub innym zabezpieczeniem), aby prywatne informacje użytkownika były chronione przed dostępem z zewnątrz.
- Źródło danych biometrycznych (ukryte domyślnie) jest wyświetlane w celu integracji z czujnikiem odcisku palca lub twarzy.
Kod źródłowy tych źródeł Centrum bezpieczeństwa jest dostępny w wyszukiwarce kodu Androida. Jeśli aplikacja Ustawienia nie została zmodyfikowana (nie wprowadzono zmian w nazwie pakietu, kodzie źródłowym lub kodzie źródłowym, który dotyczy ekranu blokady i funkcji biometrycznej), integracja powinna działać od razu po zainstalowaniu. W przeciwnym razie mogą być wymagane pewne modyfikacje, takie jak zmiana pliku konfiguracji w celu zmiany nazwy pakietu aplikacji Ustawienia i źródeł, które integrują się z Centrum bezpieczeństwa, a także integracja. Więcej informacji znajdziesz w pliku konfiguracji i ustawieniach integracji.
Informacje o oczekującej intencji
Jeśli korzystasz z obecnej integracji Centrum bezpieczeństwa z aplikacją Ustawienia w Androidzie 14 lub nowszym, błąd opisany poniżej został już naprawiony. W tym przypadku nie musisz czytać tej sekcji.
Gdy będziesz mieć pewność, że błąd nie istnieje, ustaw wartość konfiguracji zasobu logicznego XML w aplikacji Ustawienia config_isSafetyCenterLockScreenPendingIntentFixed
na true
, aby wyłączyć obejście w Centrum bezpieczeństwa.
Rozwiązanie dotyczące PendingIntent
Ten błąd jest spowodowany tym, że Ustawienia używają dodatkowych elementów instancji Intent
do określenia, który fragment otworzyć. Ponieważ Intent#equals
nie uwzględnia dodatkowych informacji w Intent
, instancja PendingIntent
dla ikony menu koła zębatego i wejścia są traktowane jako równe i przechodzą do tego samego interfejsu użytkownika (nawet jeśli są przeznaczone do przechodzenia do innego interfejsu). Ten problem został rozwiązany w wersji QPR przez rozróżnienie wystąpień PendingIntent
według kodu żądania. Można też odróżnić je za pomocą atrybutu Intent#setId
.
Wewnętrzne źródła bezpieczeństwa
Niektóre źródła Centrum bezpieczeństwa są wewnętrzne i są wdrażane w aplikacji systemowej PermissionController w ramach modułu PermissionController. Te źródła działają jak zwykłe źródła w Centrum bezpieczeństwa i nie są traktowane w żaden szczególny sposób. Kod tych źródeł jest dostępny w wyszukiwarce kodu na Androida.
Są to głównie sygnały dotyczące prywatności, takie jak:
- Ułatwienia dostępu
- Automatyczne odbieranie uprawnień nieużywanym aplikacjom
- Dostęp do lokalizacji
- Odbiornik powiadomień
- Informacje o zasadach służbowych