Reindirizzamento al Centro sicurezza
Qualsiasi app può aprire Safety Center utilizzando l'azione android.content.Intent.ACTION_SAFETY_CENTER
(valore stringa android.intent.action.SAFETY_CENTER
).
Per aprire Safety Center, effettua una chiamata dall'interno di un'istanza Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
Reindirizzamento a un problema specifico
È anche possibile reindirizzare a una specifica scheda di avviso di Safety Center utilizzando specifici extra per intenti. Questi extra non sono destinati a essere utilizzati da terze parti, quindi fanno parte di SafetyCenterManager
, che fa parte di @SystemApi
. Solo le app di sistema possono accedere a questi extra.
Extra di intenti che reindirizzano una specifica scheda di avviso:
-
EXTRA_SAFETY_SOURCE_ID
- Valore stringa:
android.safetycenter.extra.SAFETY_SOURCE_ID
- Tipo stringa: specifica l'ID della fonte di sicurezza della scheda di avvertenza associata
- Necessario affinché il reindirizzamento al problema funzioni
- Valore stringa:
-
EXTRA_SAFETY_SOURCE_ISSUE_ID
- Valore stringa:
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- Tipo di stringa: specifica l'ID della scheda di avviso
- Necessario affinché il reindirizzamento al problema funzioni
- Valore stringa:
-
EXTRA_SAFETY_SOURCE_USER_HANDLE
- Valore stringa:
android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
- Tipo
UserHandle
: specificaUserHandle
per la scheda di avviso associata - Facoltativo (l'impostazione predefinita è l'utente corrente)
- Valore stringa:
Lo snippet di codice riportato di seguito può essere utilizzato dall'interno di un'istanza Activity
per aprire la schermata del Centro sicurezza su un problema specifico:
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);
Reindirizzamento a una pagina secondaria specifica (a partire da Android 14)
In Android 14 o versioni successive, la pagina Safety Center è suddivisa in più sottopagine che rappresentano i diversi SafetySourcesGroup
(in Android 13, questo viene visualizzato come voci comprimibili).
È possibile reindirizzare a una sottopagina specifica utilizzando questo intento extra:
-
EXTRA_SAFETY_SOURCES_GROUP_ID
- Valore stringa:
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- Tipo di stringa: specifica l'ID di
SafetySourcesGroup
- Necessario affinché il reindirizzamento alla sottopagina funzioni
- Valore stringa:
Lo snippet di codice riportato di seguito può essere utilizzato dall'interno di un'istanza Activity
per aprire la schermata del Centro sicurezza su una pagina secondaria specifica:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");
startActivity(openSafetyCenterIntent);
Utilizza le API di origine del Centro sicurezza
Le API di origine di Safety Center sono disponibili utilizzando SafetyCenterManager
(che è un @SystemApi
). Il codice per la superficie API è disponibile in Ricerca codice . Il codice di implementazione delle API è disponibile in Ricerca codice .
Autorizzazioni
Le API di origine del Centro sicurezza sono accessibili solo dalle app di sistema autorizzate utilizzando le autorizzazioni elencate di seguito. Per ulteriori informazioni, consulta Elenco consentito delle autorizzazioni privilegiate .
-
READ_SAFETY_CENTER_STATUS
-
signature|privileged
- Utilizzato per l'API
SafetyCenterManager#isSafetyCenterEnabled()
(non necessario per le origini Safety Center, richiedono solo l'autorizzazioneSEND_SAFETY_CENTER_UPDATE
) - Utilizzato dalle app di sistema che controllano se il Centro sicurezza è abilitato
- Concesso solo alle app di sistema incluse nella lista consentita
-
-
SEND_SAFETY_CENTER_UPDATE
-
internal|privileged
- Utilizzato per l'API abilitata e l'API Safety Sources
- Utilizzato solo da fonti di sicurezza
- Concesso solo alle app di sistema incluse nella lista consentita
-
Queste autorizzazioni sono privilegiate e puoi acquisirle solo aggiungendole al file pertinente, ad esempio il file com.android.settings.xml
per l'app Impostazioni e al file AndroidManifest.xml
dell'app. Vedi protectionLevel
per ulteriori informazioni sul modello di autorizzazione.
Ottieni SafetyCenterManager
SafetyCenterManager
è una classe @SystemApi
accessibile dalle app di sistema a partire da Android 13. Questa chiamata mostra come ottenere 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;
}
Controlla se il Centro sicurezza è abilitato
Questa chiamata controlla se Safety Center è abilitato. La chiamata richiede l'autorizzazione READ_SAFETY_CENTER_STATUS
o SEND_SAFETY_CENTER_UPDATE
:
boolean isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled();
if (isSafetyCenterEnabled) {
// …
} else {
// …
}
Fornire dati
I dati di origine di Safety Center con la String sourceId
specificata vengono forniti a Safety Center con l'oggetto SafetySourceData
, che rappresenta una voce dell'interfaccia utente e un elenco di problemi (schede di avviso). La voce dell'interfaccia utente e le schede di avvertenza possono avere diversi livelli di gravità specificati nella classe SafetySourceData
:
-
SEVERITY_LEVEL_UNSPECIFIED
- Nessuna gravità specificata
- Colore: grigio o trasparente (a seconda del
SafetySourcesGroup
della voce) - Utilizzato per dati dinamici che si presentano come una voce statica nell'interfaccia utente o per mostrare una voce non specificata
- Non deve essere utilizzato per le carte di avvertimento
-
SEVERITY_LEVEL_INFORMATION
- Informazioni di base o suggerimenti minori
- Colore: verde
-
SEVERITY_LEVEL_RECOMMENDATION
- Raccomandazione che l'utente intervenga in merito a questo problema, poiché potrebbe metterlo a rischio
- Colore: giallo
-
SEVERITY_LEVEL_CRITICAL_WARNING
- Avvertimento critico che invita l'utente a prendere provvedimenti in merito a questo problema, poiché presenta un rischio
- Colore rosso
SafetySourceData
L'oggetto SafetySourceData
è composto da una voce dell'interfaccia utente, schede di avviso e invarianti.
- Istanza
SafetySourceStatus
opzionale (voce dell'interfaccia utente) - Elenco delle istanze
SafetySourceIssue
(schede di avvertenza) - Extra
Bundle
opzionale (a partire da 14) - Invarianti:
- L'elenco
SafetySourceIssue
deve essere composto da problemi con identificatori univoci. - L'istanza
SafetySourceIssue
non deve essere di maggiore importanza rispetto aSafetySourceStatus
se presente (a meno cheSafetySourceStatus
non siaSEVERITY_LEVEL_UNSPECIFIED
, nel qual caso sono consentiti problemiSEVERITY_LEVEL_INFORMATION
). - È necessario soddisfare ulteriori requisiti imposti dalla configurazione API, ad esempio, se l'origine è solo problema, non deve fornire un'istanza
SafetySourceStatus
.
- L'elenco
SafetySourceStatus
- Titolo
CharSequence
obbligatorio - Riepilogo
CharSequence
obbligatorio - Livello di gravità richiesto
- Istanza
PendingIntent
opzionale per reindirizzare l'utente alla pagina giusta (l'impostazione predefinita utilizzaintentAction
dalla configurazione, se presente) -
IconAction
opzionale (mostrata come icona laterale sulla voce) composta da:- Tipo di icona obbligatorio, che deve essere uno dei seguenti tipi:
-
ICON_TYPE_GEAR
: mostrato come un ingranaggio accanto alla voce dell'interfaccia utente -
ICON_TYPE_INFO
: mostrato come icona di informazioni accanto alla voce dell'interfaccia utente
-
- Obbligatorio
PendingIntent
per reindirizzare l'utente a un'altra pagina
- Tipo di icona obbligatorio, che deve essere uno dei seguenti tipi:
- Valore booleano
enabled
facoltativo che consente di contrassegnare la voce dell'interfaccia utente come disabilitata, quindi non è selezionabile (l'impostazione predefinita ètrue
) - Invarianti:
- Le istanze
PendingIntent
devono aprire un'istanzaActivity
. - Se la voce è disabilitata, deve essere designata
SEVERITY_LEVEL_UNSPECIFIED
. - Requisiti aggiuntivi imposti dalla configurazione API.
- Le istanze
SafetySourceIssue
- Identificatore
String
univoco obbligatorio - Titolo
CharSequence
obbligatorio - Sottotitolo
CharSequence
opzionale - Riepilogo
CharSequence
obbligatorio - Livello di gravità richiesto
- Categoria di problema facoltativa, che deve essere una delle seguenti:
-
ISSUE_CATEGORY_DEVICE
: il problema riguarda il dispositivo dell'utente. -
ISSUE_CATEGORY_ACCOUNT
: il problema riguarda gli account dell'utente. -
ISSUE_CATEGORY_GENERAL
: il problema influisce sulla sicurezza generale dell'utente. Questa è l'impostazione predefinita. -
ISSUE_CATEGORY_DATA
(a partire da Android 14): il problema riguarda i dati dell'utente. -
ISSUE_CATEGORY_PASSWORDS
(a partire da Android 14): il problema riguarda le password dell'utente. -
ISSUE_CATEGORY_PERSONAL_SAFETY
(a partire da Android 14): il problema influisce sulla sicurezza personale dell'utente.
-
- Elenco di elementi
Action
che l'utente può intraprendere per questo problema, ciascuna istanzaAction
è composta da:- Identificatore
String
univoco obbligatorio - Etichetta
CharSequence
obbligatoria - Obbligatorio
PendingIntent
per reindirizzare l'utente a un'altra pagina o elaborare l'azione direttamente dalla schermata Safety Center - Valore booleano facoltativo per specificare se questo problema può essere risolto direttamente dalla schermata Safety Center (l'impostazione predefinita è
false
) - Messaggio di successo
CharSequence
facoltativo, da visualizzare all'utente quando il problema viene risolto correttamente direttamente dalla schermata Safety Center
- Identificatore
-
PendingIntent
facoltativo che viene chiamato quando l'utente ignora il problema (per impostazione predefinita non viene chiamato nulla) - Obbligatorio Identificatore del tipo di problema
String
; questo è simile all'identificatore del problema ma non deve essere univoco e viene utilizzato per la registrazione -
String
facoltativa per l'ID di deduplicazione, consente di pubblicare lo stessoSafetySourceIssue
da fonti diverse e di mostrarlo solo una volta nell'interfaccia utente presupponendo che abbiano lo stessodeduplicationGroup
(a partire da Android 14). Se non specificato, il problema non viene mai deduplicato -
CharSequence
facoltativa per il titolo di attribuzione, si tratta di un testo che mostra l'origine della scheda di avviso (a partire da Android 14). Se non specificato utilizza il titolo diSafetySourcesGroup
- Azione facoltativa per il problema (a partire da Android 14), che deve essere uno dei seguenti:
-
ISSUE_ACTIONABILITY_MANUAL
: l'utente deve risolvere questo problema manualmente. Questa è l'impostazione predefinita. -
ISSUE_ACTIONABILITY_TIP
: questo problema è solo un suggerimento e potrebbe non richiedere alcun input da parte dell'utente. -
ISSUE_ACTIONABILITY_AUTOMATIC
: questo problema è già stato risolto e potrebbe non richiedere alcun input da parte dell'utente.
-
- Comportamento di notifica facoltativo (a partire da Android 14), che deve essere uno dei seguenti:
-
NOTIFICATION_BEHAVIOR_UNSPECIFIED
: Safety Center deciderà se è necessaria una notifica per la scheda di avvertenza. Questa è l'impostazione predefinita. -
NOTIFICATION_BEHAVIOR_NEVER
: nessuna notifica pubblicata. -
NOTIFICATION_BEHAVIOR_DELAYED
: viene pubblicata una notifica qualche tempo dopo la prima segnalazione del problema. -
NOTIFICATION_BEHAVIOR_IMMEDIATELY
: viene pubblicata una notifica non appena viene segnalato il problema.
-
-
Notification
opzionale, per mostrare una notifica personalizzata con la scheda di avviso (a partire da Android 14). Se non specificato, laNotification
è derivata dalla scheda di avvertimento. Composto da:- Titolo
CharSequence
obbligatorio - Riepilogo
CharSequence
obbligatorio - Elenco di elementi
Action
che l'utente può intraprendere per questa notifica
- Titolo
- Invarianti:
- L'elenco delle istanze
Action
deve essere composto da azioni con identificatori univoci - L'elenco delle istanze
Action
deve contenere uno o due elementiAction
. Se l'azione non èISSUE_ACTIONABILITY_MANUAL
, è consentita l'assenzaAction
. - OnDismiss
PendingIntent
non deve aprire un'istanzaActivity
- Requisiti aggiuntivi imposti dalla configurazione API
- L'elenco delle istanze
I dati vengono forniti al Safety Center in seguito a determinati eventi, quindi è necessario specificare cosa ha causato la fornitura da parte dell'origine a SafetySourceData
di un'istanza SafetyEvent
.
SafetyEvent
- Tipo obbligatorio, che deve essere uno tra:
-
SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
: lo stato della fonte è cambiato. -
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
: risposta a un segnale di aggiornamento/nuova scansione da Safety Center; utilizzare questo invece diSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
per Safety Center per poter monitorare la richiesta di aggiornamento/nuova scansione. -
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
: abbiamo risoltoSafetySourceIssue.Action
direttamente dalla schermata Safety Center; utilizzare questo invece diSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
per Safety Center per poter tenere traccia delSafetySourceIssue.Action
in fase di risoluzione. -
SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
: abbiamo tentato di risolvereSafetySourceIssue.Action
direttamente dalla schermata Safety Center, ma non siamo riusciti a farlo; utilizzare questo invece diSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
per Safety Center per poter monitorareSafetySourceIssue.Action
in caso di errore. -
SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED
: la lingua del dispositivo è cambiata, quindi aggiorniamo il testo dei dati forniti; è consentito utilizzareSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
per questo. -
SAFETY_EVENT_TYPE_DEVICE_REBOOTED
: forniamo questi dati come parte di un avvio iniziale poiché i dati di Safety Center non vengono mantenuti dopo i riavvii; è consentito utilizzareSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
per questo.
-
- Identificatore
String
facoltativo per l'ID di trasmissione di aggiornamento. - Identificatore
String
facoltativo per l'istanzaSafetySourceIssue
in fase di risoluzione. - Identificatore
String
facoltativo per l'istanzaSafetySourceIssue.Action
in fase di risoluzione. - Invarianti:
- È necessario fornire l'ID broadcast di aggiornamento se il tipo è
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
- È necessario fornire gli ID del problema e dell'azione se il tipo è
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
oSAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
- È necessario fornire l'ID broadcast di aggiornamento se il tipo è
Di seguito è riportato un esempio di come una fonte potrebbe fornire dati a Safety Center (in questo caso fornisce una voce con un'unica scheda di avviso):
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);
Ottieni gli ultimi dati forniti
Puoi ottenere gli ultimi dati forniti al Centro sicurezza per un'origine di proprietà della tua app. Puoi usarlo per far emergere qualcosa nella tua interfaccia utente, per verificare se i dati devono essere aggiornati prima di eseguire un'operazione costosa o per fornire la stessa istanza SafetySourceData
a Safety Center con alcune modifiche o con una nuova istanza SafetyEvent
. È utile anche per fare delle prove.
Utilizza questo codice per ottenere gli ultimi dati forniti a Safety Center:
SafetySourceData lastDataProvided = safetyCenterManager.getSafetySourceData("MySourceId");
Segnala un errore
Se non riesci a raccogliere i dati SafetySourceData
, puoi segnalare l'errore a Safety Center, che modifica la voce in grigio, cancella i dati memorizzati nella cache e fornisce un messaggio simile a Impossibile controllare l'impostazione . Puoi anche segnalare un errore se un'istanza di SafetySourceIssue.Action
non viene risolta, nel qual caso i dati memorizzati nella cache non vengono cancellati e la voce dell'interfaccia utente non viene modificata; ma viene visualizzato un messaggio all'utente per informarlo che qualcosa è andato storto.
Puoi fornire l'errore utilizzando SafetySourceErrorDetails
, che è composto da:
-
SafetySourceErrorDetails
: istanzaSafetyEvent
obbligatoria :
// 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);
Rispondere a una richiesta di aggiornamento o nuova scansione
Puoi ricevere un segnale dal Centro sicurezza per fornire nuovi dati. La risposta a una richiesta di aggiornamento o nuova scansione garantisce che l'utente visualizzi lo stato corrente quando apre Safety Center e quando tocca il pulsante di scansione.
Questo viene fatto ricevendo una trasmissione con la seguente azione:
-
ACTION_REFRESH_SAFETY_SOURCES
- Valore stringa:
android.safetycenter.action.REFRESH_SAFETY_SOURCES
- Attivato quando Safety Center invia una richiesta di aggiornamento dei dati dell'origine di sicurezza per una determinata app
- Intento protetto che può essere inviato solo dal sistema
- Inviato a tutte le origini di sicurezza nel file di configurazione come intento esplicito e richiede l'autorizzazione
SEND_SAFETY_CENTER_UPDATE
- Valore stringa:
I seguenti extra sono forniti come parte di questa trasmissione:
-
EXTRA_REFRESH_SAFETY_SOURCE_IDS
- Valore stringa:
android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
- Il tipo di array di stringhe (
String[]
) rappresenta gli ID di origine da aggiornare per l'app specificata
- Valore stringa:
EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Valore stringa:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Tipo intero, rappresenta un tipo di richiesta
@IntDef
- Deve essere uno di:
-
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
: richiede all'origine di fornire dati in modo relativamente veloce, in genere quando l'utente apre la pagina -
EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA
: richiede all'origine di fornire dati quanto più aggiornati possibile, in genere quando l'utente preme il pulsante di nuova scansione
-
- Valore stringa:
EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Valore stringa:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Tipo stringa, rappresenta un identificatore univoco per l'aggiornamento richiesto
- Valore stringa:
Per ottenere un segnale dal Safety Center, implementa un'istanza BroadcastReceiver
. La trasmissione viene inviata con speciali BroadcastOptions
che consentono al ricevitore di avviare un servizio in primo piano.
BroadcastReceiver
risponde a una richiesta di aggiornamento:
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;
}
}
La stessa istanza di BroadcastReceiver
nell'esempio precedente è dichiarata in 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>
Idealmente, un'origine Safety Center viene implementata in modo tale da richiamare SafetyCenterManager
quando i relativi dati cambiano. Per motivi di integrità del sistema, consigliamo di rispondere solo al segnale di nuova scansione (quando l'utente tocca il pulsante di scansione) e non quando l'utente apre il Centro sicurezza. Se questa funzionalità è richiesta, il campo refreshOnPageOpenAllowed="true"
nel file di configurazione deve essere impostato affinché l'origine riceva la trasmissione trasmessa in questi casi.
Rispondi al Centro sicurezza quando abilitato o disabilitato
Puoi rispondere a quando il Centro sicurezza è abilitato o disabilitato utilizzando questa azione di intento:
-
ACTION_SAFETY_CENTER_ENABLED_CHANGED
- Valore stringa:
android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
- Si attiva quando Safety Center è abilitato o disabilitato mentre il dispositivo è in esecuzione
- Non richiamato all'avvio (utilizza
ACTION_BOOT_COMPLETED
per questo) - Intento protetto che può essere inviato solo dal sistema
- Inviato a tutte le origini di sicurezza nel file di configurazione come intento esplicito, richiede l'autorizzazione
SEND_SAFETY_CENTER_UPDATE
- Inviato come intento implicito che richiede l'autorizzazione
READ_SAFETY_CENTER_STATUS
- Valore stringa:
Questa azione intent è utile per abilitare o disabilitare le funzionalità correlate a Safety Center sul dispositivo.
Implementare azioni risolutive
Un'azione di risoluzione è un'istanza SafetySourceIssue.Action
che un utente può risolvere direttamente dalla schermata Safety Center. L'utente tocca un pulsante di azione e viene attivata l'istanza PendingIntent
su SafetySourceIssue.Action
inviata dall'origine di sicurezza, che risolve il problema in background e avvisa il Centro sicurezza al termine.
Per implementare le azioni di risoluzione, l'origine di Safety Center può utilizzare un servizio se si prevede che l'operazione richieda del tempo ( PendingIntent.getService
) o un ricevitore di trasmissione ( PendingIntent.getBroadcast
).
Utilizza questo codice per inviare un problema di risoluzione al Centro sicurezza:
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
risolve l'azione:
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).
}
}
La stessa istanza di BroadcastReceiver
nell'esempio precedente è dichiarata in 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>
Rispondere ai licenziamenti
È possibile specificare un'istanza PendingIntent
che può essere attivata quando un'istanza SafetySourceIssue
viene ignorata. Il Centro sicurezza gestisce i licenziamenti di questi problemi:
- Se una fonte segnala un problema, un utente può ignorarlo nella schermata Safety Center toccando il pulsante Ignora (un pulsante X sulla scheda di avviso).
- Quando un utente ignora un problema, se il problema persiste, non verrà più visualizzato nell'interfaccia utente.
- I licenziamenti persistenti su un disco rimangono durante i riavvii del dispositivo.
- Se l'origine del Centro sicurezza smette di fornire un problema e lo fornisce nuovamente in un secondo momento, il problema si ripresenta. Questo per consentire situazioni in cui un utente vede un avviso, lo ignora, quindi intraprende un'azione che dovrebbe alleviare il problema, ma poi l'utente fa di nuovo qualcosa che causa un problema simile. A questo punto, la carta di avvertimento dovrebbe riaffiorare.
- Le schede di avviso gialle e rosse riappaiono ogni 180 giorni, a meno che l'utente non le abbia ignorate più volte.
La fonte non dovrebbe richiedere comportamenti aggiuntivi a meno che:
- La fonte tenta di implementare questo comportamento in modo diverso, ad esempio, senza mai far riemergere il problema.
- La fonte tenta di utilizzarlo come callback, ad esempio, per registrare le informazioni.
Fornire dati per più utenti/profili
L'API SafetyCenterManager
può essere utilizzata tra utenti e profili diversi. Per ulteriori informazioni, consulta Creazione di app multiutente . L'oggetto Context
che fornisce SafetyCenterManager
è associato a un'istanza UserHandle
, quindi l'istanza SafetyCenterManager
restituita interagisce con il Safety Center per quell'istanza UserHandle
. Per impostazione predefinita, Context
è associato all'utente in esecuzione, ma è possibile creare un'istanza per un altro utente se l'app dispone delle autorizzazioni INTERACT_ACROSS_USERS
e INTERACT_ACROSS_USERS_FULL
. Questo esempio mostra come effettuare una chiamata tra utenti/profili:
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
Ciascun utente del dispositivo può avere più profili gestiti. Il Centro Sicurezza fornisce dati diversi per ciascun utente, ma unisce i dati di tutti i profili gestiti associati a un determinato utente.
Quando profile="all_profiles"
è impostato per l'origine nel file di configurazione, si verifica quanto segue:
- È presente una voce dell'interfaccia utente per l'utente (profilo principale) e tutti i relativi profili gestiti associati (che utilizzano istanze
titleForWork
). Il segnale di aggiornamento o nuova scansione viene inviato per il profilo principale e tutti i profili gestiti associati. Il ricevitore associato viene avviato per ciascun profilo e può fornire i dati associati direttamente a
SafetyCenterManager
senza dover effettuare una chiamata tra profili, a meno che il ricevitore o l'app non sianosingleUser
.Si prevede che la fonte fornisca dati per l'utente e tutti i suoi profili gestiti. I dati per ciascuna voce dell'interfaccia utente potrebbero essere diversi a seconda del profilo.
Test
puoi accedere ShadowSafetyCenterManager
e utilizzarlo in un test 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);
}
È possibile scrivere più test end-to-end (E2E), ma ciò non rientra nell'ambito di questa guida. Per ulteriori informazioni sulla scrittura di questi test E2E, vedere test CTS (CtsSafetyCenterTestCases)
Test e API interne
Le API interne e le API di test sono per uso interno, pertanto non sono descritte in dettaglio in questa guida. Tuttavia, in futuro potremmo estendere alcune API interne per consentire agli OEM di creare la propria interfaccia utente e aggiorneremo questa guida per fornire indicazioni su come utilizzarle.
Autorizzazioni
-
MANAGE_SAFETY_CENTER
-
internal|installer|role
- Utilizzato per le API interne del Centro sicurezza
- Concesso solo a PermissionController e shell
-
Applicazione Impostazioni
Reindirizzamento del Centro sicurezza
Per impostazione predefinita, è possibile accedere al Centro sicurezza tramite l'app Impostazioni con una nuova voce Sicurezza e privacy . Se utilizzi un'app Impostazioni diversa o se hai modificato l'app Impostazioni, potrebbe essere necessario personalizzare la modalità di accesso al Centro sicurezza.
Quando Safety Center è abilitato:
- La voce Legacy Privacy è un codice nascosto
- La voce Legacy Security è un codice nascosto
- Viene aggiunto un codice alla nuova voce Sicurezza e privacy
- La nuova voce Sicurezza e privacy reindirizza al codice del Centro sicurezza
- Le azioni intent
android.settings.PRIVACY_SETTINGS
eandroid.settings.SECURITY_SETTINGS
vengono reindirizzate all'apertura del Centro sicurezza (codice: security , privacy )
Pagine di sicurezza e privacy avanzate
L'app Impostazioni contiene impostazioni aggiuntive nei titoli Altre impostazioni di sicurezza e Altre impostazioni sulla privacy , disponibili nel Centro sicurezza:
Codice di sicurezza avanzato
Codice privacy avanzato
A partire da Android 14, la pagina delle impostazioni avanzate di sicurezza e privacy viene unita in un'unica pagina "Più sicurezza e privacy" con l'azione di intento
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
Fonti di sicurezza
Safety Center si integra con un set specifico di fonti di sicurezza fornite dall'app Impostazioni:
- Un'origine di sicurezza della schermata di blocco verifica che una schermata di blocco sia configurata con un passcode (o altra sicurezza), per garantire che le informazioni private dell'utente siano protette da accessi esterni.
- Una fonte di sicurezza biometrica (nascosta per impostazione predefinita) emerge per l'integrazione con un sensore di impronte digitali o facciale.
Il codice sorgente di queste fonti del Centro sicurezza è accessibile tramite la ricerca del codice Android . Se l'app Impostazioni non viene modificata (non vengono apportate modifiche al nome del pacchetto, al codice sorgente o al codice sorgente che gestisce una schermata di blocco e dati biometrici), questa integrazione dovrebbe funzionare immediatamente. In caso contrario, potrebbero essere necessarie alcune modifiche, ad esempio la modifica del file di configurazione per modificare il nome del pacchetto dell'app Impostazioni e le origini che si integrano con Safety Center, nonché l'integrazione. Per ulteriori informazioni, consulta Aggiornamento del file di configurazione e delle impostazioni di integrazione .
Informazioni su PendingIntent
Se ti affidi all'integrazione esistente dell'app Impostazioni Safety Center in Android 14 o versioni successive, il bug descritto di seguito è stato corretto. In questo caso non è necessario leggere questa sezione.
Quando sei sicuro che il bug non esista, imposta un valore di configurazione della risorsa booleana XML nell'app Impostazioni config_isSafetyCenterLockScreenPendingIntentFixed
su true
per disattivare la soluzione alternativa all'interno di Safety Center.
Soluzione alternativa PendingIntent
Questo bug è causato dalle Impostazioni che utilizzano gli extra dell'istanza Intent
per determinare quale frammento aprire. Poiché Intent#equals
non tiene conto degli extra dell'istanza Intent
, l'istanza PendingIntent
per l'icona del menu a forma di ingranaggio e la voce sono considerate uguali e passano alla stessa interfaccia utente (anche se sono destinate a passare a un'interfaccia utente diversa). Questo problema viene risolto in una versione QPR differenziando le istanze PendingIntent
in base al codice di richiesta. In alternativa, questo potrebbe essere differenziato utilizzando Intent#setId
.
Fonti interne di sicurezza
Alcune origini di Safety Center sono interne e sono implementate nell'app di sistema PermissionController all'interno del modulo PermissionController. Queste origini si comportano come le normali origini del Centro sicurezza e non ricevono alcun trattamento speciale. Il codice per queste origini è disponibile tramite la ricerca del codice Android .
Si tratta principalmente di segnali relativi alla privacy, ad esempio:
- Accessibilità
- Revoca automaticamente le app inutilizzate
- Accesso alla posizione
- Ascoltatore di notifiche
- Informazioni sulla politica del lavoro