Interagire con il Centro per la sicurezza online

Reindirizza al Centro per la sicurezza online

Qualsiasi app può aprire il Centro per la sicurezza online utilizzando l'azione android.content.Intent.ACTION_SAFETY_CENTER (valore di stringa android.intent.action.SAFETY_CENTER).

Per aprire il Centro per la sicurezza online, effettua una chiamata da un'istanza Activity:

Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);

startActivity(openSafetyCenterIntent);

Reindirizzare a un problema specifico

È anche possibile reindirizzare a una scheda di avviso del Centro sicurezza specifica utilizzando parametri aggiuntivi per gli intent specifici. Poiché non sono pensati per essere utilizzati da terze parti, fanno parte di SafetyCenterManager, che fa parte di @SystemApi. Solo le app di sistema possono accedere a questi extra.

Componenti aggiuntivi dell'intent che reindirizzano a una scheda di avviso specifica:

  • EXTRA_SAFETY_SOURCE_ID
    • Valore stringa: android.safetycenter.extra.SAFETY_SOURCE_ID
    • Tipo di stringa: specifica l'ID dell'origine di sicurezza della scheda di avviso associata
    • Obbligatorio per il funzionamento del reindirizzamento al problema
  • EXTRA_SAFETY_SOURCE_ISSUE_ID
    • Valore stringa: android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
    • Tipo di stringa: specifica l'ID della scheda di avviso
    • Obbligatorio per il funzionamento del reindirizzamento al problema
  • EXTRA_SAFETY_SOURCE_USER_HANDLE
    • Valore stringa: android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
    • Tipo UserHandle: specifica UserHandle per la scheda di avviso associata
    • Facoltativo (il valore predefinito è l'utente corrente)

Lo snippet di codice riportato di seguito può essere utilizzato all'interno di un'istanza Activity per aprire la schermata del Centro di sicurezza in corrispondenza di 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);

Reindirizzare a una sottopagina specifica (a partire da Android 14)

In Android 14 o versioni successive, la pagina Centro sicurezza è suddivisa in più sottopagine che rappresentano i diversi SafetySourcesGroup (in Android 13, vengono visualizzate come voci comprimibili).

È possibile reindirizzare a una sottopagina specifica utilizzando questo elemento aggiuntivo dell'intent:

  • EXTRA_SAFETY_SOURCES_GROUP_ID
    • Valore stringa: android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
    • Tipo di stringa: specifica l'ID del SafetySourcesGroup
    • Obbligatorio per il funzionamento del reindirizzamento alla sottopagina

Lo snippet di codice riportato di seguito può essere utilizzato all'interno di un'istanza Activity per aprire la schermata del Centro per la sicurezza in una sottopagina specifica:

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

startActivity(openSafetyCenterIntent);

Utilizzare le API di origine di Safety Center

Le API di origine di Safety Center sono disponibili utilizzando SafetyCenterManager (che è un @SystemApi). Il codice per l'interfaccia API è disponibile in Ricerca codice. Il codice di implementazione delle API è disponibile in Ricerca codice.

Autorizzazioni

Le API di origine di Safety Center sono accessibili solo dalle app di sistema inserite nella lista consentita che utilizzano le autorizzazioni elencate di seguito. Per ulteriori informazioni, consulta la sezione Lista consentita di autorizzazioni privilegiate.

  • READ_SAFETY_CENTER_STATUS
    • signature|privileged
    • Utilizzato per l'API SafetyCenterManager#isSafetyCenterEnabled() (non necessario per le origini di Safety Center, che richiedono solo l'autorizzazione SEND_SAFETY_CENTER_UPDATE)
    • Utilizzato dalle app di sistema che controllano se il Centro sicurezza è attivo
    • Concessi 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
    • Concessi solo alle app di sistema incluse nella lista consentita

Queste autorizzazioni sono privilegiate e puoi acquisirle solo aggiungendole al file pertinente, ad esempio al file com.android.settings.xml per l'app Impostazioni e al file AndroidManifest.xml dell'app. Per ulteriori informazioni sul modello di autorizzazione, consulta protectionLevel.

Recuperare SafetyCenterManager

SafetyCenterManager è una classe @SystemApi accessibile dalle app di sistema a partire da Android 13. Questa chiamata mostra come recuperare 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;
}

Verificare se è attivo il Centro di sicurezza

Questa chiamata verifica se il Centro sicurezza è attivo. 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 il valore String sourceId specificato 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 avviso possono avere diversi livelli di gravità specificati nella classe SafetySourceData:

  • SEVERITY_LEVEL_UNSPECIFIED
    • Gravità non specificata
    • Colore: grigio o trasparente (a seconda del SafetySourcesGroup della voce)
    • Utilizzato per i 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 schede di avviso
  • SEVERITY_LEVEL_INFORMATION
    • Informazioni di base o suggerimento minore
    • Colore: verde
  • SEVERITY_LEVEL_RECOMMENDATION
    • Consiglio all'utente di intervenire in merito al problema, in quanto potrebbe metterlo a rischio
    • Colore: giallo
  • SEVERITY_LEVEL_CRITICAL_WARNING
    • Avviso critico che indica che l'utente deve intervenire in merito al problema, poiché rappresenta un rischio
    • Colore: rosso

SafetySourceData

L'oggetto SafetySourceData è composto da una voce dell'interfaccia utente, schede di avviso e immutabili.

  • Istanza SafetySourceStatus facoltativa (voce dell'interfaccia utente)
  • Elenco di istanze SafetySourceIssue (schede di avviso)
  • Extra Bundle facoltativi (a partire dalla versione 14)
  • Invarianze:
    • L'elenco SafetySourceIssue deve essere composto da problemi con identificatori univoci.
    • L'istanza SafetySourceIssue non deve avere un'importanza maggiore di SafetySourceStatus, se presente (a meno che SafetySourceStatus non sia SEVERITY_LEVEL_UNSPECIFIED, nel qual caso sono consentiti problemi SEVERITY_LEVEL_INFORMATION).
    • Devono essere soddisfatti requisiti aggiuntivi imposti dalla configurazione dell'API, ad esempio, se l'origine è solo per problemi, non deve fornire un'istanza SafetySourceStatus.

SafetySourceStatus

  • Titolo CharSequence obbligatorio
  • Riepilogo obbligatorio di CharSequence
  • Livello di gravità richiesto
  • Istanza facoltativa PendingIntent per reindirizzare l'utente alla pagina corretta (per impostazione predefinita viene utilizzato intentAction dalla configurazione, se presente)
  • IconAction facoltativo (visualizzato come icona laterale nella voce) composto da:
    • Tipo di icona obbligatorio, che deve essere uno dei seguenti:
      • ICON_TYPE_GEAR: visualizzato come ingranaggio accanto alla voce dell'interfaccia utente
      • ICON_TYPE_INFO: viene visualizzata come icona informativa accanto alla voce dell'interfaccia utente
    • Obbligatorio PendingIntent per reindirizzare l'utente a un'altra pagina
  • Valore booleano facoltativo enabled che consente di contrassegnare la voce dell'interfaccia utente come disabilitata, in modo che non sia selezionabile (il valore predefinito è true).
  • Invarianze:
    • Le istanze PendingIntent devono aprire un'istanza Activity.
    • Se la voce è disattivata, deve essere designata come SEVERITY_LEVEL_UNSPECIFIED.
    • Requisiti aggiuntivi imposti dalla configurazione dell'API.

SafetySourceIssue

  • Identificatore String univoco obbligatorio
  • Titolo CharSequence obbligatorio
  • Sottotitolo CharSequence facoltativo
  • Riepilogo obbligatorio di CharSequence
  • 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 riguarda la 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 riguarda la sicurezza personale dell'utente.
  • Elenco di elementi Action che l'utente può adottare per questo problema, ciascuna istanza Action 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 del Centro per la sicurezza online
    • Valore booleano facoltativo per specificare se il problema può essere risolto direttamente dalla schermata del Centro sicurezza (il valore predefinito è false)
    • Messaggio di conferma facoltativo CharSequence da mostrare all'utente quando il problema è stato risolto correttamente direttamente dalla schermata del Centro sicurezza
  • PendingIntent facoltativo che viene chiamato quando l'utente ignora il problema (per impostazione predefinita non viene chiamato nessun metodo)
  • Identificatore del tipo di problema String obbligatorio; è simile all'identificatore del problema, ma non deve essere univoco e viene utilizzato per la registrazione
  • String facoltativo per l'ID di deduplica, che consente di pubblicare lo stesso SafetySourceIssue da origini diverse e di mostrarlo una sola volta nell' interfaccia utente, supponendo che abbiano lo stesso deduplicationGroup (a partire da Android 14). Se non specificato, il problema non viene mai deduplicato
  • CharSequence facoltativo per il titolo dell'attribuzione, si tratta di un testo che mostra la provenienza della scheda di avviso (a partire da Android 14). Se non specificato, viene utilizzato il titolo del SafetySourcesGroup
  • Azione facoltativa per i problemi (a partire da Android 14), che deve essere una delle seguenti:
    • ISSUE_ACTIONABILITY_MANUAL: l'utente deve risolvere il 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: è già stato intrapreso un provvedimento per questo problema e potrebbe non essere necessario alcun intervento da parte dell'utente.
  • Comportamento facoltativo delle notifiche (a partire da Android 14), che deve essere uno dei seguenti:
    • NOTIFICATION_BEHAVIOR_UNSPECIFIED: il Centro sicurezza deciderà se è necessaria una notifica per la scheda dell'avviso. Questa è l'impostazione predefinita.
    • NOTIFICATION_BEHAVIOR_NEVER: nessuna notifica viene pubblicata.
    • NOTIFICATION_BEHAVIOR_DELAYED: una notifica viene pubblicata qualche tempo dopo la prima segnalazione del problema.
    • NOTIFICATION_BEHAVIOR_IMMEDIATELY: viene inviata una notifica non appena il problema viene segnalato.
  • (Facoltativo) Notification, per mostrare una notifica personalizzata con la scheda di avviso (a partire da Android 14). Se non specificato, il valore Notification viene ricavato dalla scheda dell'avviso. Composto da:
    • Titolo CharSequence obbligatorio
    • Riepilogo obbligatorio di CharSequence
    • Elenco di elementi Action che l'utente può eseguire per questa notifica
  • Invarianze:
    • L'elenco di istanze Action deve essere composto da azioni con identificatori univoci
    • L'elenco di istanze Action deve contenere uno o due elementi Action. Se l'azione non è ISSUE_ACTIONABILITY_MANUAL, è consentito avere Action pari a zero.
    • L'evento OnDismiss PendingIntent non deve aprire un'istanza Activity
    • Requisiti aggiuntivi imposti dalla configurazione dell'API

I dati vengono forniti al Centro per la sicurezza in base a determinati eventi, pertanto è necessario specificare cosa ha causato l'invio da parte dell'origine di un'istanza SafetySourceData.SafetyEvent

SafetyEvent

  • Tipo obbligatorio, che deve essere uno dei seguenti:
    • SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED: lo stato dell'origine è cambiato.
    • SAFETY_EVENT_TYPE_REFRESH_REQUESTED: risposta a un indicazione di aggiornamento/nuova ricerca da parte del Centro sicurezza. Utilizzalo al posto di SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED per consentire al Centro sicurezza di monitorare la richiesta di aggiornamento/nuova ricerca.
    • SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED: abbiamo risolto SafetySourceIssue.Action direttamente dalla schermata del Centro sicurezza. Utilizza questo valore anziché SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED per il Centro sicurezza per poter monitorare la risoluzione di SafetySourceIssue.Action.
    • SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED: abbiamo tentato di risolvere il problema SafetySourceIssue.Action direttamente dalla schermata del Centro sicurezza, ma non ci siamo riusciti. Utilizza questo valore anziché SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED per consentire al Centro sicurezza di monitorare il fallimento di SafetySourceIssue.Action.
    • SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED: la lingua del dispositivo è cambiata, quindi stiamo aggiornando il testo dei dati forniti. Per questo è consentito utilizzare SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED.
    • SAFETY_EVENT_TYPE_DEVICE_REBOOTED: forniamo questi dati nell'ambito di un avvio iniziale poiché i dati del Centro sicurezza non vengono mantenuti durante i riavvii. È consentito utilizzare SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED per questo scopo.
  • Identificatore String facoltativo per l'ID trasmissione dell'aggiornamento.
  • Identificatore facoltativo String per l'istanza SafetySourceIssue da risolvere.
  • Identificatore String facoltativo per l'istanza SafetySourceIssue.Action in fase di risoluzione.
  • Invarianze:
    • L'ID trasmissione di aggiornamento deve essere fornito se il tipo è SAFETY_EVENT_TYPE_REFRESH_REQUESTED
    • Gli ID problema e azione devono essere forniti se il tipo è SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED o SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED

Di seguito è riportato un esempio di come un'origine potrebbe fornire dati a Safety Center (in questo caso fornisce una voce con una singola 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);

Ottenere gli ultimi dati forniti

Puoi ottenere gli ultimi dati forniti a Safety Center per un'origine di proprietà della tua app. Puoi utilizzarli per visualizzare qualcosa nella tua UI, per verificare se i dati devono essere aggiornati prima di eseguire un'operazione dispendiosa o per fornire la stessa istanza SafetySourceData a Safety Center con alcune modifiche o con una nuova istanza SafetyEvent. È utile anche per i test.

Utilizza questo codice per recuperare gli ultimi dati forniti a Centro sicurezza:

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

Segnalare un errore

Se non riesci a raccogliere i dati SafetySourceData, puoi segnalare l'errore a Safety Centre, che rende grigia la voce, 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 riesce a risolvere, 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 per informare l'utente che si è verificato un problema.

Puoi fornire l'errore utilizzando SafetySourceErrorDetails, che è composto da:

  • SafetySourceErrorDetails: istanza SafetyEvent 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 il Centro sicurezza 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
    • Si attiva quando il Centro sicurezza invia una richiesta di aggiornamento dei dati dell'origine di sicurezza per una determinata app
    • Intent protetto che può essere inviato solo dal sistema
    • Inviata a tutte le origini di sicurezza nel file di configurazione come intent esplicito e richiede l'autorizzazione SEND_SAFETY_CENTER_UPDATE

Nell'ambito di questa trasmissione vengono forniti i seguenti extra:

  • EXTRA_REFRESH_SAFETY_SOURCE_IDS
    • Valore stringa: android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
    • Tipo di array di stringhe (String[]), rappresenta gli ID origine da aggiornare per la determinata app
  • 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 dei seguenti:
      • EXTRA_REFRESH_REQUEST_TYPE_GET_DATA: richiede all'origine di fornire i dati in modo relativamente rapido, in genere quando l'utente apre la pagina
      • EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA: richiede all'origine di fornire i dati più aggiornati possibili, in genere quando l'utente preme il pulsante di nuova ricerca
  • EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID

    • Valore stringa: android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
    • Tipo di stringa, rappresenta un identificatore univoco per l'aggiornamento richiesto

Per ricevere un avviso dal Centro per la sicurezza, implementa un'istanza BroadcastReceiver. La trasmissione viene inviata con un BroadcastOptions speciale che consente al transceiver 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 del Centro sicurezza viene implementata in modo da chiamare SafetyCenterManager quando i dati cambiano. Per motivi di integrità del sistema, consigliamo di rispondere solo all'indicatore di nuova ricerca (quando l'utente tocca il pulsante di ricerca) e non quando l'utente apre il Centro sicurezza. Se questa funzionalità è obbligatoria, il campo refreshOnPageOpenAllowed="true" nel file di configurazione deve essere impostato in modo che l'origine riceva la trasmissione in questi casi.

.

Rispondere al Centro di sicurezza quando è attivo o disattivato

Puoi rispondere quando il Centro di sicurezza è attivato o disattivato utilizzando questa azione di intent:

  • ACTION_SAFETY_CENTER_ENABLED_CHANGED
    • Valore stringa: android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
    • Viene attivato quando il Centro di sicurezza è attivato o disattivato mentre il dispositivo è in esecuzione
    • Non viene chiamato all'avvio (per questo, usa ACTION_BOOT_COMPLETED
    • Intent protetto che può essere inviato solo dal sistema
    • Inviata a tutte le origini di sicurezza nel file di configurazione come intent esplicito, richiede l'autorizzazione SEND_SAFETY_CENTER_UPDATE
    • Inviata come intent implicito che richiede l'autorizzazione READ_SAFETY_CENTER_STATUS

Questa azione di intent è utile per attivare o disattivare le funzionalità relative a Centro sicurezza sul dispositivo.

Implementa le azioni di risoluzione

Un'azione di risoluzione è un'istanza SafetySourceIssue.Action che un utente può risolvere direttamente dalla schermata del Centro per la sicurezza online. 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 invia una notifica al Centro per la sicurezza online al termine.

Per implementare le azioni di risoluzione, l'origine Centro di sicurezza può utilizzare un servizio se l'operazione dovrebbe richiedere del tempo (PendingIntent.getService) o un ricevitore di trasmissione (PendingIntent.getBroadcast).

Usa questo codice per inviare un problema di risoluzione al Centro per la 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 alla chiusura dei problemi

Puoi specificare un'istanza PendingIntent che può essere attivata quando un'istanza SafetySourceIssue viene ignorata. Il Centro per la sicurezza gestisce i seguenti chiusure dei problemi:

  • Se una fonte segnala un problema, l'utente può ignorarlo nella schermata Centro sicurezza toccando il pulsante di chiusura (un pulsante X nella scheda dell'avviso).
  • Se un utente ignora un problema, questo non verrà visualizzato nuovamente nell'interfaccia utente se il problema persiste.
  • Le chiusure permanenti su un disco rimangono durante i riavvii del dispositivo.
  • Se l'origine del Centro per la sicurezza smette di segnalare un problema e poi lo segnala di nuovo in un secondo momento, il problema si ripresenta. Questo per consentire situazioni in cui un utente vede un avviso, lo ignora e poi 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 scheda dell'avviso dovrebbe essere visualizzata di nuovo.
  • Le schede di avviso gialle e rosse vengono visualizzate di nuovo ogni 180 giorni, a meno che l'utente non le abbia chiuse più volte.

L'origine non dovrebbe richiedere comportamenti aggiuntivi, a meno che:

  • La sorgente tenta di implementare questo comportamento in modo diverso, ad esempio non facendo mai riemergere il problema.
  • L'origine tenta di utilizzarlo come callback, ad esempio per registrare le informazioni.

Fornire dati per più utenti/profili

L'API SafetyCenterManager può essere utilizzata su utenti e profili. Per ulteriori informazioni, consulta la sezione Creare app consapevoli del multiutente. L'oggetto Context che fornisce SafetyCenterManager è associato a un'istanza UserHandle, pertanto l'istanza SafetyCenterManager restituita interagisce con il Centro per la sicurezza 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

Ogni utente sul dispositivo può avere più profili gestiti. Il Centro per la sicurezza fornisce dati diversi per ogni 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, avviene quanto segue:

  • Esiste una voce dell'interfaccia utente per l'utente (profilo principale) e per tutti i relativi profili gestiti associati (che utilizzano istanze titleForWork).
  • L'indicatore di aggiornamento o nuova scansione viene inviato per il profilo principale e per tutti i profili gestiti associati. Il destinatario associato viene avviato per ogni profilo e può fornire i dati associati direttamente a SafetyCenterManager senza dover effettuare una chiamata tra profili, a meno che il destinatario o l'app non sia singleUser.

  • L'origine deve fornire i dati dell'utente e di tutti i suoi profili gestiti. I dati di ogni voce dell'interfaccia utente potrebbero essere diversi a seconda del profilo.

Test

Puoi accedere a 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);
}

Puoi scrivere altri test end-to-end (E2E), ma non rientrano nell'ambito di questa guida. Per ulteriori informazioni sulla scrittura di questi test E2E, consulta Test CTS (CtsSafetyCenterTestCases)

API di test e interne

Le API interne e di test sono destinate all'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 UI e aggiorneremo questa guida per fornire indicazioni su come utilizzarle.

Autorizzazioni

  • MANAGE_SAFETY_CENTER
    • internal|installer|role
    • Utilizzato per le API di Safety Center interne
    • Concessi solo a PermissionController e shell

App Impostazioni

Riindirizzo al Centro per la sicurezza online

Per impostazione predefinita, si accede 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, potresti dover personalizzare la modalità di accesso a Centro di sicurezza.

Quando è attivo il Centro di sicurezza:

  • Codice della voce Privacy legacy nascosta
  • La voce Sicurezza legacy è un codice nascosto
  • Viene aggiunta una nuova voce Sicurezza e privacy codice
  • La nuova voce Sicurezza e privacy reindirizza al codice del Centro sicurezza
  • Le azioni di intent android.settings.PRIVACY_SETTINGS e android.settings.SECURITY_SETTINGS vengono reindirizzate per aprire il Centro per la sicurezza online (codice: security, privacy)

Pagine di sicurezza e privacy avanzate

L'app Impostazioni contiene impostazioni aggiuntive nelle sezioni Altre impostazioni di sicurezza e Altre impostazioni della privacy, disponibili nel Centro per la sicurezza online:

Origini di sicurezza

Safety Center si integra con un insieme specifico di origini di sicurezza fornite dall'app Impostazioni:

  • Un'origine di sicurezza della schermata di blocco verifica che sia impostata una schermata di blocco con un passcode (o un'altra misura di sicurezza) per garantire che le informazioni private dell'utente siano al sicuro da accessi esterni.
  • Viene visualizzata un'origine di sicurezza biometrica (nascosta per impostazione predefinita) da integrare con un sensore di impronte o del volto.

Il codice sorgente di queste origini del Centro sicurezza è accessibile tramite la ricerca di 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 si occupa della schermata di blocco e della biometria), 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 integrate con il Centro sicurezza, nonché l'integrazione stessa. Per ulteriori informazioni, vedi Aggiornare il file di configurazione e le impostazioni di integrazione.

Informazioni su PendingIntent

Se utilizzi l'integrazione esistente del Centro sicurezza nell'app Impostazioni in Android 14 o versioni successive, il bug descritto di seguito è stato corretto. In questo caso, non è necessario leggere questa sezione.

Quando hai la certezza che il bug non esista, imposta un valore di configurazione della risorsa booleana XML nell'app Impostazioniconfig_isSafetyCenterLockScreenPendingIntentFixed su true per disattivare la soluzione alternativa in Centro sicurezza.

Soluzione alternativa per PendingIntent

Questo bug è causato dal fatto che le impostazioni utilizzano gli extra dell'istanza Intent per determinare quale frammento aprire. Poiché Intent#equals non prende in considerazione gli elementi aggiuntivi dell'istanza Intent, l'istanza PendingIntent per l'icona del menu a forma di ingranaggio e la voce sono considerate uguali e rimandano alla stessa UI (anche se è prevista la navigazione verso un'UI diversa). Questo problema è stato risolto in una release QPR differenziando le istanze PendingIntent in base al codice richiesta. In alternativa, questo può essere differenziato utilizzando Intent#setId.

Origini di sicurezza interne

Alcune origini del Centro sicurezza sono interne e vengono implementate nell'app di sistema PermissionController all'interno del modulo PermissionController. Queste fonti si comportano come le normali fonti del Centro sicurezza e non ricevono alcun trattamento speciale. Il codice per queste origini è disponibile tramite la Ricerca codice Android.

Si tratta principalmente di indicatori sulla privacy, ad esempio:

  • Accessibilità
  • Revocare automaticamente le autorizzazioni per le app inutilizzate
  • Accesso alla posizione
  • Listener di notifica
  • Informazioni sulle norme di lavoro