Rediriger vers le centre de sécurité
N'importe quelle application peut ouvrir Safety Center à l'aide de l'action android.content.Intent.ACTION_SAFETY_CENTER
(valeur de chaîne android.intent.action.SAFETY_CENTER
).
Pour ouvrir Safety Center, passez un appel depuis une instance Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
Rediriger vers un problème spécifique
Il est également possible de rediriger vers une carte d'avertissement spécifique du Centre de sécurité à l'aide d'extras d'intention spécifiques. Ces extras ne sont pas destinés à être utilisés par des tiers et font donc partie de SafetyCenterManager
, qui fait partie de @SystemApi
. Seules les applications système peuvent accéder à ces extras.
Extras d'intention qui redirigent une carte d'avertissement spécifique :
-
EXTRA_SAFETY_SOURCE_ID
- Valeur de chaîne :
android.safetycenter.extra.SAFETY_SOURCE_ID
- Type de chaîne : Spécifie l'ID de la source de sécurité de la carte d'avertissement associée
- Nécessaire pour que la redirection vers le problème fonctionne
- Valeur de chaîne :
-
EXTRA_SAFETY_SOURCE_ISSUE_ID
- Valeur de chaîne :
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- Type de chaîne : spécifie l'ID de la carte d'avertissement
- Nécessaire pour que la redirection vers le problème fonctionne
- Valeur de chaîne :
-
EXTRA_SAFETY_SOURCE_USER_HANDLE
- Valeur de chaîne :
android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
- Type
UserHandle
: SpécifieUserHandle
pour la carte d'avertissement associée. - Facultatif (la valeur par défaut est l'utilisateur actuel)
- Valeur de chaîne :
L'extrait de code ci-dessous peut être utilisé à partir d'une instance Activity
pour ouvrir l'écran Safety Center pour un problème spécifique :
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);
Redirection vers une sous-page spécifique (à partir d'Android 14)
Dans Android 14 ou version ultérieure, la page Safety Center est divisée en plusieurs sous-pages qui représentent les différents SafetySourcesGroup
(dans Android 13, cela s'affiche sous forme d'entrées réductibles).
Il est possible de rediriger vers une sous-page spécifique en utilisant cette intention supplémentaire :
-
EXTRA_SAFETY_SOURCES_GROUP_ID
- Valeur de chaîne :
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- Type de chaîne : spécifie l'ID du
SafetySourcesGroup
- Nécessaire pour que la redirection vers la sous-page fonctionne
- Valeur de chaîne :
L'extrait de code ci-dessous peut être utilisé à partir d'une instance Activity
pour ouvrir l'écran Safety Center vers une sous-page spécifique :
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");
startActivity(openSafetyCenterIntent);
Utiliser les API sources de Safety Center
Les API sources de Safety Center sont disponibles à l'aide SafetyCenterManager
(qui est un @SystemApi
). Le code de la surface API est disponible dans Code Search . Le code d'implémentation des API est disponible dans Code Search .
Autorisations
Les API sources de Safety Center ne sont accessibles que par les applications système sur liste blanche utilisant les autorisations répertoriées ci-dessous. Pour plus d’informations, consultez Liste d’autorisation des autorisations privilégiées .
-
READ_SAFETY_CENTER_STATUS
-
signature|privileged
- Utilisé pour l'API
SafetyCenterManager#isSafetyCenterEnabled()
(non nécessaire pour les sources Safety Center, elles n'ont besoin que de l'autorisationSEND_SAFETY_CENTER_UPDATE
) - Utilisé par les applications système qui vérifient si le centre de sécurité est activé
- Accordé uniquement aux applications système sur liste blanche
-
-
SEND_SAFETY_CENTER_UPDATE
-
internal|privileged
- Utilisé pour l'API activée et l'API Safety Sources
- Utilisé uniquement par des sources de sécurité
- Accordé uniquement aux applications système sur liste blanche
-
Ces autorisations sont privilégiées et vous ne pouvez les acquérir qu'en les ajoutant au fichier approprié, par exemple, le fichier com.android.settings.xml
pour l'application Paramètres et au fichier AndroidManifest.xml
de l'application. Voir protectionLevel
pour plus d’informations sur le modèle d’autorisation.
Obtenez le SafetyCenterManager
SafetyCenterManager
est une classe @SystemApi
accessible à partir des applications système à partir d'Android 13. Cet appel montre comment obtenir 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;
}
Vérifiez si le centre de sécurité est activé
Cet appel vérifie si Safety Center est activé. L'appel nécessite l'autorisation READ_SAFETY_CENTER_STATUS
ou SEND_SAFETY_CENTER_UPDATE
:
boolean isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled();
if (isSafetyCenterEnabled) {
// …
} else {
// …
}
Fournir des données
Les données source de Safety Center avec la String sourceId
donnée sont fournies à Safety Center avec l'objet SafetySourceData
, qui représente une entrée d'interface utilisateur et une liste de problèmes (cartes d'avertissement). L'entrée de l'interface utilisateur et les cartes d'avertissement peuvent avoir différents niveaux de gravité spécifiés dans la classe SafetySourceData
:
-
SEVERITY_LEVEL_UNSPECIFIED
- Aucune gravité spécifiée
- Couleur : Gris ou transparent (selon le
SafetySourcesGroup
de l'entrée) - Utilisé pour les données dynamiques qui se présentent comme une entrée statique dans l'interface utilisateur ou pour afficher une entrée non spécifiée
- Ne doit pas être utilisé pour les cartes d'avertissement
-
SEVERITY_LEVEL_INFORMATION
- Informations de base ou suggestion mineure
- La couleur verte
-
SEVERITY_LEVEL_RECOMMENDATION
- Recommandation à l'utilisateur d'agir sur ce problème, car cela pourrait le mettre en danger
- Couleur jaune
-
SEVERITY_LEVEL_CRITICAL_WARNING
- Avertissement critique indiquant que l'utilisateur doit prendre des mesures face à ce problème, car il présente un risque
- La couleur rouge
SafetySourceData
L'objet SafetySourceData
est composé d'une entrée d'interface utilisateur, de cartes d'avertissement et d'invariants.
- Instance
SafetySourceStatus
facultative (entrée d’interface utilisateur) - Liste des instances
SafetySourceIssue
(cartes d'avertissement) - Extras
Bundle
en option (à partir du 14) - Invariants :
- La liste
SafetySourceIssue
doit être composée de problèmes avec des identifiants uniques. - L'instance
SafetySourceIssue
ne doit pas être plus importante queSafetySourceStatus
s'il y en a une (sauf siSafetySourceStatus
estSEVERITY_LEVEL_UNSPECIFIED
, auquel cas les problèmesSEVERITY_LEVEL_INFORMATION
sont autorisés). - Des exigences supplémentaires imposées par la configuration de l'API doivent être respectées. Par exemple, si la source concerne uniquement les problèmes, elle ne doit pas fournir d'instance
SafetySourceStatus
.
- La liste
SafetySourceStatus
- Titre
CharSequence
requis - Résumé
CharSequence
requis - Niveau de gravité requis
- Instance
PendingIntent
facultative pour rediriger l'utilisateur vers la bonne page (la valeur par défaut utiliseintentAction
de la configuration, le cas échéant) -
IconAction
facultative (affichée sous la forme d'une icône latérale sur l'entrée) composée de :- Type d'icône obligatoire, qui doit être l'un des types suivants :
-
ICON_TYPE_GEAR
: affiché sous la forme d'un engrenage à côté de l'entrée de l'interface utilisateur -
ICON_TYPE_INFO
: affiché sous la forme d'une icône d'information à côté de l'entrée de l'interface utilisateur
-
-
PendingIntent
requis pour rediriger l'utilisateur vers une autre page
- Type d'icône obligatoire, qui doit être l'un des types suivants :
- Valeur booléenne
enabled
facultative qui permet de marquer l'entrée de l'interface utilisateur comme désactivée, afin qu'elle ne soit pas cliquable (la valeur par défaut esttrue
) - Invariants :
- Les instances
PendingIntent
doivent ouvrir une instanceActivity
. - Si l'entrée est désactivée, elle doit être désignée
SEVERITY_LEVEL_UNSPECIFIED
. - Exigences supplémentaires imposées par la configuration de l'API.
- Les instances
SafetySourceIssue
- Identificateur
String
unique requis - Titre
CharSequence
requis - Sous-titre
CharSequence
facultatif - Résumé
CharSequence
requis - Niveau de gravité requis
- Catégorie de problème facultative, qui doit être l’une des suivantes :
-
ISSUE_CATEGORY_DEVICE
: le problème affecte l'appareil de l'utilisateur. -
ISSUE_CATEGORY_ACCOUNT
: le problème affecte les comptes de l'utilisateur. -
ISSUE_CATEGORY_GENERAL
: le problème affecte la sécurité générale de l'utilisateur. C'est la valeur par défaut. -
ISSUE_CATEGORY_DATA
(à partir d'Android 14) : le problème affecte les données de l'utilisateur. -
ISSUE_CATEGORY_PASSWORDS
(à partir d’Android 14) : le problème affecte les mots de passe de l’utilisateur. -
ISSUE_CATEGORY_PERSONAL_SAFETY
(à partir d'Android 14) : le problème affecte la sécurité personnelle de l'utilisateur.
-
- Liste des éléments
Action
que l'utilisateur peut prendre pour ce problème, chaque instanceAction
étant composée de :- Identificateur
String
unique requis - Libellé
CharSequence
requis -
PendingIntent
requis pour rediriger l'utilisateur vers une autre page ou traiter l'action directement à partir de l'écran Safety Center - Booléen facultatif pour spécifier si ce problème peut être résolu directement à partir de l'écran Safety Center (la valeur par défaut est
false
) - Message de réussite
CharSequence
facultatif, à afficher à l'utilisateur lorsque le problème est résolu avec succès directement à partir de l'écran du Centre de sécurité.
- Identificateur
-
PendingIntent
facultatif appelé lorsque l'utilisateur rejette le problème (par défaut, rien n'est appelé) - Identifiant du type de problème
String
obligatoire ; ceci est similaire à l'identifiant du problème mais ne doit pas nécessairement être unique et est utilisé pour la journalisation -
String
facultative pour l’ID de déduplication, cela permet de publier le mêmeSafetySourceIssue
à partir de différentes sources et de l’afficher une seule fois dans l’interface utilisateur en supposant qu’ils ont le mêmededuplicationGroup
(à partir d’Android 14). S'il n'est pas spécifié, le problème n'est jamais dédupliqué -
CharSequence
facultatif pour le titre d'attribution, il s'agit d'un texte qui indique l'origine de la carte d'avertissement (à partir d'Android 14). S’il n’est pas spécifié, utilise le titre duSafetySourcesGroup
- Possibilité d'action facultative en cas de problème (à partir d'Android 14), qui doit être l'une des suivantes :
-
ISSUE_ACTIONABILITY_MANUAL
: l'utilisateur doit résoudre ce problème manuellement. C'est la valeur par défaut. -
ISSUE_ACTIONABILITY_TIP
: ce problème n'est qu'un conseil et ne nécessite aucune intervention de l'utilisateur. -
ISSUE_ACTIONABILITY_AUTOMATIC
: ce problème a déjà été résolu et peut ne nécessiter aucune intervention de l'utilisateur.
-
- Comportement de notification facultatif (à partir d'Android 14), qui doit être l'un des suivants :
-
NOTIFICATION_BEHAVIOR_UNSPECIFIED
: Safety Center décidera si une notification est nécessaire pour la carte d'avertissement. C'est la valeur par défaut. -
NOTIFICATION_BEHAVIOR_NEVER
: Aucune notification n'est publiée. -
NOTIFICATION_BEHAVIOR_DELAYED
: Une notification est publiée quelque temps après le premier signalement du problème. -
NOTIFICATION_BEHAVIOR_IMMEDIATELY
: Une notification est publiée dès que le problème est signalé.
-
-
Notification
facultative, pour afficher une notification personnalisée avec la carte d'avertissement (à partir d'Android 14). Si elle n'est pas spécifiée, laNotification
est dérivée de la carte d'avertissement. Composé de:- Titre
CharSequence
requis - Résumé
CharSequence
requis - Liste des éléments
Action
que l'utilisateur peut entreprendre pour cette notification
- Titre
- Invariants :
- La liste des instances
Action
doit être composée d'actions avec des identifiants uniques - La liste des instances
Action
doit contenir un ou deux élémentsAction
. Si l'actionnabilité n'est pasISSUE_ACTIONABILITY_MANUAL
, avoir zéroAction
est autorisé. - Le OnDismiss
PendingIntent
ne doit pas ouvrir une instanceActivity
- Exigences supplémentaires imposées par la configuration de l'API
- La liste des instances
Les données sont fournies lors de certains événements au Safety Center. Il est donc nécessaire de spécifier la raison pour laquelle la source a fourni à SafetySourceData
une instance SafetyEvent
.
SafetyEvent
- Type requis, qui doit être l'un des suivants :
-
SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
: L'état de la source a changé. -
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
: réponse à un signal d'actualisation/rescan du centre de sécurité ; utilisez-le au lieu deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour que Safety Center puisse suivre la demande d'actualisation/nouvelle analyse. -
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
: Nous avons résoluSafetySourceIssue.Action
directement à partir de l'écran du Centre de sécurité ; utilisez-le au lieu deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour que Safety Center puisse suivre leSafetySourceIssue.Action
en cours de résolution. -
SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
: nous avons tenté de résoudreSafetySourceIssue.Action
directement à partir de l'écran Safety Center, mais nous n'y sommes pas parvenus ; utilisez-le au lieu deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour que Safety Center puisse suivre l'échec deSafetySourceIssue.Action
. -
SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED
: La langue de l'appareil a changé, nous mettons donc à jour le texte des données fournies ; il est permis d'utiliserSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour cela. -
SAFETY_EVENT_TYPE_DEVICE_REBOOTED
: nous fournissons ces données dans le cadre d'un démarrage initial, car les données de Safety Center ne sont pas conservées lors des redémarrages ; il est permis d'utiliserSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour cela.
-
- Identificateur
String
facultatif pour l’ID de diffusion d’actualisation. - Identificateur
String
facultatif pour l’instanceSafetySourceIssue
en cours de résolution. - Identificateur
String
facultatif pour l’instanceSafetySourceIssue.Action
en cours de résolution. - Invariants :
- L'ID de diffusion d'actualisation doit être fourni si le type est
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
- Les ID de problème et d'action doivent être fournis si le type est
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
ouSAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
.
- L'ID de diffusion d'actualisation doit être fourni si le type est
Vous trouverez ci-dessous un exemple de la manière dont une source peut fournir des données à Safety Center (dans ce cas, il s'agit de fournir une entrée avec une seule carte d'avertissement) :
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);
Obtenir les dernières données fournies
Vous pouvez obtenir les dernières données fournies à Safety Center pour une source appartenant à votre application. Vous pouvez l'utiliser pour afficher quelque chose dans votre propre interface utilisateur, pour vérifier si les données doivent être mises à jour avant d'effectuer une opération coûteuse, ou pour fournir la même instance SafetySourceData
à Safety Center avec quelques modifications ou avec une nouvelle instance SafetyEvent
. C'est également utile pour les tests.
Utilisez ce code pour obtenir les dernières données fournies à Safety Center :
SafetySourceData lastDataProvided = safetyCenterManager.getSafetySourceData("MySourceId");
Signaler une erreur
Si vous ne parvenez pas à collecter les données SafetySourceData
, vous pouvez signaler l'erreur à Safety Center, qui change l'entrée en gris, efface les données mises en cache et fournit un message du genre Impossible de vérifier les paramètres . Vous pouvez également signaler une erreur si une instance de SafetySourceIssue.Action
ne parvient pas à être résolue, auquel cas les données mises en cache ne sont pas effacées et l'entrée de l'interface utilisateur n'est pas modifiée ; mais un message est adressé à l'utilisateur pour lui faire savoir que quelque chose s'est mal passé.
Vous pouvez fournir l'erreur à l'aide de SafetySourceErrorDetails
, qui est composé de :
-
SafetySourceErrorDetails
: instanceSafetyEvent
requise :
// 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);
Répondre à une demande d'actualisation ou de nouvelle analyse
Vous pouvez recevoir un signal du centre de sécurité pour fournir de nouvelles données. Répondre à une demande d'actualisation ou de nouvelle analyse garantit que l'utilisateur visualise l'état actuel lors de l'ouverture de Safety Center et lorsqu'il appuie sur le bouton d'analyse.
Cela se fait en recevant une diffusion avec l'action suivante :
-
ACTION_REFRESH_SAFETY_SOURCES
- Valeur de chaîne :
android.safetycenter.action.REFRESH_SAFETY_SOURCES
- Déclenché lorsque Safety Center envoie une demande d'actualisation des données de la source de sécurité pour une application donnée
- Intention protégée qui ne peut être envoyée que par le système
- Envoyé à toutes les sources de sécurité dans le fichier de configuration en tant qu'intention explicite et nécessite l'autorisation
SEND_SAFETY_CENTER_UPDATE
- Valeur de chaîne :
Les extras suivants sont fournis dans le cadre de cette diffusion :
-
EXTRA_REFRESH_SAFETY_SOURCE_IDS
- Valeur de chaîne :
android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
- Type de tableau de chaînes (
String[]
), représente les ID source à actualiser pour l'application donnée
- Valeur de chaîne :
EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Valeur de chaîne :
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Type entier, représente un type de requête
@IntDef
- Doit être l'un des :
-
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
: demande à la source de fournir des données relativement rapidement, généralement lorsque l'utilisateur ouvre la page -
EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA
: demande à la source de fournir des données aussi récentes que possible, généralement lorsque l'utilisateur appuie sur le bouton de nouvelle analyse.
-
- Valeur de chaîne :
EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Valeur de chaîne :
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Type de chaîne, représente un identifiant unique pour l'actualisation demandée
- Valeur de chaîne :
Pour obtenir un signal du Safety Center, implémentez une instance BroadcastReceiver
. La diffusion est envoyée avec BroadcastOptions
spéciales qui permettent au récepteur de démarrer un service de premier plan.
BroadcastReceiver
répond à une demande d'actualisation :
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 même instance de BroadcastReceiver
dans l'exemple ci-dessus est déclarée dans 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>
Idéalement, une source Safety Center est implémentée de telle manière qu'elle appelle SafetyCenterManager
lorsque ses données changent. Pour des raisons de santé du système, nous vous recommandons de répondre uniquement au signal de nouvelle analyse (lorsque l'utilisateur appuie sur le bouton d'analyse), et non lorsque l'utilisateur ouvre le Centre de sécurité. Si cette fonctionnalité est requise, le champ refreshOnPageOpenAllowed="true"
dans le fichier de configuration doit être défini pour que la source reçoive la diffusion délivrée dans ces cas.
Répondre au centre de sécurité lorsqu'il est activé ou désactivé
Vous pouvez répondre lorsque le centre de sécurité est activé ou désactivé en utilisant cette action d'intention :
-
ACTION_SAFETY_CENTER_ENABLED_CHANGED
- Valeur de chaîne :
android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
- Déclenché lorsque le centre de sécurité est activé ou désactivé pendant que l'appareil est en cours d'exécution
- Non appelé au démarrage (utilisez
ACTION_BOOT_COMPLETED
pour cela) - Intention protégée qui ne peut être envoyée que par le système
- Envoyé à toutes les sources de sécurité dans le fichier de configuration en tant qu'intention explicite, nécessite l'autorisation
SEND_SAFETY_CENTER_UPDATE
- Envoyé en tant qu'intention implicite nécessitant l'autorisation
READ_SAFETY_CENTER_STATUS
- Valeur de chaîne :
Cette action d'intention est utile pour activer ou désactiver les fonctionnalités liées à Safety Center sur l'appareil.
Mettre en œuvre des actions de résolution
Une action de résolution est une instance SafetySourceIssue.Action
qu'un utilisateur peut résoudre directement à partir de l'écran Safety Center. L'utilisateur appuie sur un bouton d'action et l'instance PendingIntent
sur SafetySourceIssue.Action
envoyée par la source de sécurité est déclenchée, ce qui résout le problème en arrière-plan et informe le centre de sécurité lorsque l'opération est terminée.
Pour implémenter des actions de résolution, la source Safety Center peut utiliser un service si l'opération devrait prendre un certain temps ( PendingIntent.getService
) ou un récepteur de diffusion ( PendingIntent.getBroadcast
).
Utilisez ce code pour envoyer un problème de résolution à Safety Center :
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
résout l’action :
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 même instance de BroadcastReceiver
dans l'exemple ci-dessus est déclarée dans 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>
Répondre aux licenciements
Vous pouvez spécifier une instance PendingIntent
qui peut être déclenchée lorsqu'une instance SafetySourceIssue
est rejetée. Le Centre de Sécurité gère ces licenciements problématiques :
- Si une source soulève un problème, un utilisateur peut le rejeter sur l'écran du Centre de sécurité en appuyant sur le bouton Ignorer (un bouton X sur la carte d'avertissement).
- Lorsqu'un utilisateur ignore un problème, si le problème persiste, il ne réapparaîtra plus dans l'interface utilisateur.
- Les licenciements persistants sur un disque restent lors des redémarrages de l'appareil.
- Si la source du Safety Center cesse de signaler un problème, puis le signale à nouveau ultérieurement, le problème refait surface. Il s'agit de permettre les situations dans lesquelles un utilisateur voit un avertissement, le rejette, puis prend des mesures qui devraient atténuer le problème, mais l'utilisateur refait ensuite quelque chose qui provoque un problème similaire. À ce stade, la carte d’avertissement devrait refaire surface.
- Les cartes d'avertissement jaunes et rouges réapparaissent tous les 180 jours, sauf si l'utilisateur les a ignorées plusieurs fois.
Des comportements supplémentaires ne devraient pas être requis par la source, sauf :
- La source essaie de mettre en œuvre ce comportement différemment, par exemple, de ne jamais ressusciter le problème.
- La source essaie de l'utiliser comme rappel, par exemple, pour enregistrer les informations.
Fournir des données pour plusieurs utilisateurs/profils
L'API SafetyCenterManager
peut être utilisée entre les utilisateurs et les profils. Pour plus d'informations, consultez Création d'applications multi-utilisateurs . L'objet Context
qui fournit SafetyCenterManager
est associé à une instance UserHandle
, de sorte que l'instance SafetyCenterManager
renvoyée interagit avec le Safety Center pour cette instance UserHandle
. Par défaut, Context
est associé à l'utilisateur en cours d'exécution, mais il est possible de créer une instance pour un autre utilisateur si l'application détient les autorisations INTERACT_ACROSS_USERS
et INTERACT_ACROSS_USERS_FULL
. Cet exemple montre l'émission d'un appel entre utilisateurs/profils :
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
Chaque utilisateur de l'appareil peut avoir plusieurs profils gérés. Le Safety Center fournit des données différentes pour chaque utilisateur, mais fusionne les données de tous les profils gérés associés à un utilisateur donné.
Lorsque profile="all_profiles"
est défini pour la source dans le fichier de configuration, les événements suivants se produisent :
- Il existe une entrée d'interface utilisateur pour l'utilisateur (parent du profil) et tous ses profils gérés associés (qui utilisent des instances
titleForWork
). Le signal d'actualisation ou de nouvelle analyse est envoyé pour le profil parent et tous les profils gérés associés. Le récepteur associé est démarré pour chaque profil et peut fournir les données associées directement à
SafetyCenterManager
sans avoir à effectuer un appel entre profils, sauf si le récepteur ou l'application estsingleUser
.La source est censée fournir des données sur l'utilisateur et tous ses profils gérés. Les données de chaque entrée de l'interface utilisateur peuvent être différentes selon le profil.
Essai
vous pouvez accéder ShadowSafetyCenterManager
et l'utiliser dans 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);
}
Vous pouvez écrire davantage de tests de bout en bout (E2E), mais cela sort du cadre de ce guide. Pour plus d'informations sur l'écriture de ces tests E2E, voir Tests CTS (CtsSafetyCenterTestCases)
Test et API internes
Les API internes et les API de test sont destinées à un usage interne et ne sont donc pas décrites en détail dans ce guide. Cependant, nous pourrions étendre certaines API internes à l'avenir pour permettre aux OEM de créer leur propre interface utilisateur et nous mettrons à jour ce guide pour fournir des conseils sur la façon de les utiliser.
Autorisations
-
MANAGE_SAFETY_CENTER
-
internal|installer|role
- Utilisé pour les API internes du Safety Center
- Accordé uniquement à PermissionController et au shell
-
Application Paramètres
Redirection du centre de sécurité
Par défaut, le Centre de sécurité est accessible via l'application Paramètres avec une nouvelle entrée Sécurité et confidentialité . Si vous utilisez une autre application Paramètres ou si vous avez modifié l'application Paramètres, vous devrez peut-être personnaliser la manière dont vous accédez au Centre de sécurité.
Lorsque le Centre de sécurité est activé :
- L'entrée de confidentialité héritée est un code caché
- L'entrée de sécurité héritée est un code caché
- Une nouvelle entrée de sécurité et de confidentialité est ajoutée au code
- La nouvelle entrée de sécurité et de confidentialité redirige vers le code Safety Center
- Les actions d'intention
android.settings.PRIVACY_SETTINGS
etandroid.settings.SECURITY_SETTINGS
sont redirigées vers l'ouverture du Centre de sécurité (code : security , Privacy )
Pages avancées de sécurité et de confidentialité
L'application Paramètres contient des paramètres supplémentaires sous les titres Plus de paramètres de sécurité et Plus de paramètres de confidentialité , disponibles dans Safety Center :
Code de sécurité avancé
Code de confidentialité avancé
À partir d'Android 14, la page des paramètres de sécurité et de confidentialité avancés est fusionnée sous une seule page « Plus de sécurité et de confidentialité » avec l'action d'intention
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
Sources de sécurité
Safety Center s'intègre à un ensemble spécifique de sources de sécurité fournies par l'application Paramètres :
- Une source de sécurité d'écran de verrouillage vérifie qu'un écran de verrouillage est configuré avec un mot de passe (ou une autre sécurité), pour garantir que les informations privées de l'utilisateur sont protégées de tout accès externe.
- Une source de sécurité biométrique (masquée par défaut) apparaît pour s'intégrer à un capteur d'empreintes digitales ou de visage.
Le code source de ces sources Safety Center est accessible via la recherche de code Android . Si l'application Paramètres n'est pas modifiée (aucune modification n'est apportée au nom du package, au code source ou au code source qui traite de l'écran de verrouillage et de la biométrie), alors cette intégration devrait fonctionner immédiatement. Sinon, certaines modifications pourraient être nécessaires, telles que la modification du fichier de configuration pour changer le nom du package de l'application Paramètres et les sources qui s'intègrent à Safety Center, ainsi que l'intégration. Pour plus d'informations, consultez Mettre à jour le fichier de configuration et les paramètres d'intégration .
À propos de l'intention en attente
Si vous comptez sur l’intégration existante de l’application Paramètres Safety Center dans Android 14 ou version ultérieure, le bug décrit ci-dessous a été corrigé. La lecture de cette section n'est pas nécessaire dans ce cas.
Lorsque vous êtes sûr que le bogue n'existe pas, définissez une valeur de configuration de ressource booléenne XML dans l'application Paramètres config_isSafetyCenterLockScreenPendingIntentFixed
sur true
pour désactiver la solution de contournement dans Safety Center.
Solution de contournement en attente d'intention
Ce bogue est dû au fait que les paramètres utilisent des extras d'instance Intent
pour déterminer quel fragment ouvrir. Étant donné que Intent#equals
ne prend pas en compte les extras de l'instance Intent
, l'instance PendingIntent
pour l'icône du menu d'engrenage et l'entrée sont considérées comme égales et naviguent vers la même interface utilisateur (même si elles sont destinées à naviguer vers une interface utilisateur différente). Ce problème est résolu dans une version QPR en différenciant les instances PendingIntent
par code de demande. Alternativement, cela pourrait être différencié en utilisant Intent#setId
.
Sources de sécurité internes
Certaines sources Safety Center sont internes et sont implémentées dans l'application système PermissionController au sein du module PermissionController. Ces sources se comportent comme des sources normales du Safety Center et ne reçoivent aucun traitement spécial. Le code de ces sources est disponible via la recherche de code Android .
Il s'agit principalement de signaux de confidentialité, par exemple :
- Accessibilité
- Révoquer automatiquement les applications inutilisées
- Accès à la localisation
- Écouteur de notifications
- Informations sur la politique de travail