Redirection vers le Centre de sécurité
N'importe quelle application peut ouvrir le Centre de sécurité à l'aide de l'action android.content.Intent.ACTION_SAFETY_CENTER
(valeur de chaîne android.intent.action.SAFETY_CENTER
).
Pour ouvrir le centre de sécurité, passez un appel depuis une instance Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
Rediriger vers un problème spécifique
Vous pouvez également rediriger vers une fiche d'avertissement spécifique du Centre de sécurité à l'aide d'extras d'intent spécifiques. Ces extras ne sont pas destinés à être utilisés par des tiers. Ils font donc partie de SafetyCenterManager
, qui fait partie de @SystemApi
. Seules les applications système peuvent accéder à ces extras.
Éléments supplémentaires d'intent qui rediriger une fiche 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 fiche d'avertissement associée
- Obligatoire 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 fiche d'avertissement
- Obligatoire 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 fiche d'avertissement associée - Facultatif (l'utilisateur actuel est défini par défaut)
- Valeur de chaîne:
L'extrait de code ci-dessous peut être utilisé à partir d'une instance Activity
pour ouvrir l'écran du centre de sécurité sur 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);
Rediriger vers une sous-page spécifique (à partir d'Android 14)
Sous Android 14 ou version ultérieure, la page du centre de sécurité est divisée en plusieurs sous-pages qui représentent les différents SafetySourcesGroup
(sous Android 13, elles s'affichent sous forme d'entrées réductibles).
Vous pouvez rediriger vers une sous-page spécifique à l'aide de cet extra d'intent:
EXTRA_SAFETY_SOURCES_GROUP_ID
- Valeur de chaîne:
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- Type de chaîne: spécifie l'ID de l'
SafetySourcesGroup
- Obligatoire 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 du centre de sécurité sur 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 source du Centre de sécurité
Les API sources du Safety Center sont disponibles à l'aide de SafetyCenterManager
(qui est un @SystemApi
). Le code de la surface de l'API est disponible dans la recherche de code.
Le code d'implémentation des API est disponible dans Recherche de code.
Autorisations
Les API sources du Centre de sécurité ne sont accessibles qu'aux applications système de la liste d'autorisation à l'aide des autorisations listées ci-dessous. Pour en savoir plus, consultez la section 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, qui 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ée uniquement aux applications système de la liste d'autorisation
SEND_SAFETY_CENTER_UPDATE
internal|privileged
- Utilisé pour l'API activée et l'API Safety Sources
- Utilisé par les sources de sécurité uniquement
- Accordée uniquement aux applications système de la liste d'autorisation
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. Pour en savoir plus sur le modèle d'autorisations, consultez protectionLevel
.
Obtenir le SafetyCenterManager
SafetyCenterManager
est une classe @SystemApi
accessible depuis les 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érifier si le Centre de sécurité est activé
Cet appel vérifie si le centre de sécurité 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 sources du centre de sécurité avec l'String sourceId
donné sont fournies au centre de sécurité avec l'objet SafetySourceData
, qui représente une entrée d'interface utilisateur et une liste de problèmes (fiches d'avertissement). La saisie de l'UI et les fiches d'avertissement peuvent avoir des niveaux de gravité différents 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'UI ou pour afficher une entrée non spécifiée
- Ne doit pas être utilisé pour les fiches d'avertissement
SEVERITY_LEVEL_INFORMATION
- Informations de base ou suggestion mineure
- Couleur: Vert
SEVERITY_LEVEL_RECOMMENDATION
- Recommandation à l'utilisateur de prendre des mesures concernant ce problème, car il pourrait le mettre en danger
- Couleur: Jaune
SEVERITY_LEVEL_CRITICAL_WARNING
- Avertissement critique indiquant que l'utilisateur doit prendre des mesures concernant ce problème, car il présente un risque
- Couleur: Rouge
SafetySourceData
L'objet SafetySourceData
se compose d'une entrée d'interface utilisateur, de cartes d'avertissement et d'invariants.
- Instance
SafetySourceStatus
facultative (entrée de l'interface utilisateur) - Liste des instances
SafetySourceIssue
(fiches d'avertissement) - Éléments facultatifs
Bundle
(à partir de la version 14) - Invariances :
- La liste
SafetySourceIssue
doit être composée de problèmes avec des identifiants uniques. - L'instance
SafetySourceIssue
ne doit pas être plus importante queSafetySourceStatus
, le cas échéant (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 est réservée aux problèmes, elle ne doit pas fournir d'instance
SafetySourceStatus
.
- La liste
SafetySourceStatus
- Titre
CharSequence
obligatoire - Résumé des
CharSequence
obligatoires - Niveau de gravité requis
- Instance
PendingIntent
facultative pour rediriger l'utilisateur vers la bonne page (par défaut,intentAction
est utilisé à partir de la configuration, le cas échéant) IconAction
facultatif (affiché sous forme d'icône latérale sur l'entrée) composé des éléments suivants :- Type d'icône obligatoire, qui doit être l'un des types suivants :
ICON_TYPE_GEAR
: affiché sous la forme d'une engrenage à côté de l'entrée de l'UIICON_TYPE_INFO
: affiché sous la forme d'une icône d'information à côté de l'entrée de l'UI
- Obligatoire
PendingIntent
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'UI comme désactivée, de sorte qu'elle ne soit pas cliquable (valeur par défaut :true
) - Invariances :
- Les instances
PendingIntent
doivent ouvrir une instanceActivity
. - Si l'entrée est désactivée, elle doit être désignée comme
SEVERITY_LEVEL_UNSPECIFIED
. - Exigences supplémentaires imposées par la configuration de l'API.
- Les instances
SafetySourceIssue
- Identifiant
String
unique obligatoire - Titre
CharSequence
obligatoire - Sous-titre
CharSequence
facultatif - Résumé des
CharSequence
obligatoires - 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. Il s'agit de l'option 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 des éléments suivants :- Identifiant
String
unique obligatoire - Libellé
CharSequence
obligatoire - Obligatoire
PendingIntent
pour rediriger l'utilisateur vers une autre page ou traiter l'action directement depuis l'écran du centre de sécurité - Valeur booléenne facultative indiquant si ce problème peut être résolu directement depuis l'écran du Centre de sécurité (valeur par défaut :
false
) - Message de réussite
CharSequence
facultatif, à afficher à l'utilisateur lorsque le problème est résolu directement depuis l'écran du Centre de sécurité
- Identifiant
PendingIntent
facultatif appelé lorsque l'utilisateur ignore le problème (par défaut, rien n'est appelé)- Identifiant de type de problème
String
obligatoire. Il est semblable à l'identifiant du problème, mais n'a pas besoin d'être unique et est utilisé pour la journalisation. String
facultatif pour l'ID de déduplication. Cela permet de publier le mêmeSafetySourceIssue
à partir de différentes sources et de ne l'afficher qu'une seule fois dans l'UI en supposant qu'il a le mêmededuplicationGroup
(à partir d'Android 14). Si aucune valeur n'est spécifiée, 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 fiche d'avertissement (à partir d'Android 14). Si cette option n'est pas spécifiée, le titre de l'SafetySourcesGroup
est utilisé.- Facultatif : possibilité d'actionner le problème (à partir d'Android 14), qui doit être l'une des options suivantes :
ISSUE_ACTIONABILITY_MANUAL
: L'utilisateur doit résoudre ce problème manuellement. Il s'agit de l'option par défaut.ISSUE_ACTIONABILITY_TIP
: Ce problème n'est qu'un conseil et n'a pas besoin d'une entrée utilisateur.ISSUE_ACTIONABILITY_AUTOMATIC
: Ce problème a déjà été traité et ne nécessite peut-être aucune intervention de l'utilisateur.
- Comportement des notifications facultatif (à partir d'Android 14), qui doit être l'un des suivants :
NOTIFICATION_BEHAVIOR_UNSPECIFIED
: le Centre de sécurité décide si une notification est nécessaire pour la fiche d'avertissement. Il s'agit de l'option 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
facultatif, pour afficher une notification personnalisée avec la fiche d'avertissement (à partir d'Android 14). Si aucune valeur n'est spécifiée,Notification
est dérivé de la fiche d'avertissement. Composé de :- Titre
CharSequence
obligatoire - Résumé des
CharSequence
obligatoires - Liste des éléments
Action
que l'utilisateur peut effectuer pour cette notification
- Titre
- Invariances :
- 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
, un nombre nul deAction
est autorisé. - Le
PendingIntent
OnDismiss ne doit pas ouvrir une instanceActivity
- Exigences supplémentaires imposées par la configuration de l'API
- La liste des instances
Des données sont fournies au Centre de sécurité lors de certains événements. Il est donc nécessaire de spécifier ce qui a poussé la source à fournir à SafetySourceData
une instance SafetyEvent
.
SafetyEvent
- Type obligatoire, 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épond à un signal de mise à jour/nouvelle analyse du Centre de sécurité. Utilisez-le à la place deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour que le Centre de sécurité puisse suivre la requête de mise à jour/nouvelle analyse.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
: nous avons résoluSafetySourceIssue.Action
directement depuis l'écran du Centre de sécurité. Utilisez-le à la place deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour que le Centre de sécurité puisse suivre la résolution deSafetySourceIssue.Action
.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
: nous avons tenté de résoudreSafetySourceIssue.Action
directement depuis l'écran du centre de sécurité, mais nous n'y sommes pas parvenus. Utilisez-le à la place deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour que le centre de sécurité 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. Vous pouvez utiliserSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour cela.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
: nous fournissons ces données lors d'un démarrage initial, car les données du Centre de sécurité ne sont pas conservées lors des redémarrages. Il est autorisé d'utiliserSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
pour cela.
- Identifiant
String
facultatif pour l'ID de diffusion d'actualisation. - Identifiant
String
facultatif pour l'instanceSafetySourceIssue
en cours de résolution. - Identifiant
String
facultatif pour l'instanceSafetySourceIssue.Action
en cours de résolution. - Invariances :
- 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 façon dont une source peut fournir des données au Centre de sécurité (dans ce cas, il s'agit d'une entrée avec une seule fiche 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 les utiliser pour afficher quelque chose dans votre propre UI, 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
. Cela 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 au Centre de sécurité. Il change alors la couleur de l'entrée en gris, vide les données mises en cache et affiche un message tel que Impossible de vérifier le paramètre. Vous pouvez également signaler une erreur si une instance de SafetySourceIssue.Action
ne parvient pas à résoudre le problème. Dans ce cas, les données mises en cache ne sont pas effacées et l'entrée de l'UI n'est pas modifiée. Toutefois, un message est envoyé à l'utilisateur pour l'informer qu'un problème est survenu.
Vous pouvez fournir l'erreur à l'aide de SafetySourceErrorDetails
, qui se compose des éléments suivants:
SafetySourceErrorDetails
: instanceSafetyEvent
obligatoire:
// 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 requête de rafraîchissement ou de nouvelle analyse garantit que l'utilisateur voit l'état actuel lorsqu'il ouvre le Centre de sécurité et lorsqu'il appuie sur le bouton de numérisation.
Pour ce faire, vous devez recevoir une diffusion avec l'action suivante:
ACTION_REFRESH_SAFETY_SOURCES
- Valeur de chaîne:
android.safetycenter.action.REFRESH_SAFETY_SOURCES
- Déclenché lorsque le Centre de sécurité envoie une requête pour actualiser les données de la source de sécurité d'une application donnée
- Intent protégé qui ne peut être envoyé que par le système
- Envoyée à toutes les sources de sécurité du fichier de configuration en tant qu'intent 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ésentant les ID sources à actualiser pour l'application donnée
- Valeur de chaîne:
EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Valeur de la chaîne :
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Type entier, représente un type de requête
@IntDef
- Il doit s'agir de l'un des éléments suivants :
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
: demande à la source de fournir des données relativement rapidement, généralement lorsque l'utilisateur ouvre la pageEXTRA_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 la chaîne :
EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Valeur de la 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 la chaîne :
Pour obtenir un signal du centre de sécurité, implémentez une instance BroadcastReceiver
. La diffusion est envoyée avec un BroadcastOptions
spécial qui permet au destinataire 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 manière à appeler SafetyCenterManager
lorsque ses données changent. Pour des raisons d'intégrité du système, nous vous recommandons de ne répondre qu'au signal de nouvelle analyse (lorsque l'utilisateur appuie sur le bouton de numérisation), et non lorsque l'utilisateur ouvre le centre de sécurité. Si cette fonctionnalité est requise, le champ refreshOnPageOpenAllowed="true"
du fichier de configuration doit être défini pour que la source reçoive la diffusion diffusée dans ces cas.
Répondre au Centre de sécurité lorsqu'il est activé ou désactivé
Vous pouvez répondre à l'activation ou à la désactivation du Centre de sécurité à l'aide de cette action d'intent:
ACTION_SAFETY_CENTER_ENABLED_CHANGED
- Valeur de la chaîne :
android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
- Déclenché lorsque le Centre de sécurité est activé ou désactivé lorsque l'appareil est en cours d'exécution
- Non appelé au démarrage (utilisez
ACTION_BOOT_COMPLETED
pour cela) - Intent protégé qui ne peut être envoyé que par le système
- Envoyé à toutes les sources de sécurité du fichier de configuration en tant qu'intent explicite, nécessite l'autorisation
SEND_SAFETY_CENTER_UPDATE
- Envoyée en tant qu'intent implicite nécessitant l'autorisation
READ_SAFETY_CENTER_STATUS
- Valeur de la chaîne :
Cette action d'intent est utile pour activer ou désactiver les fonctionnalités liées au Centre de sécurité sur l'appareil.
Implémenter des actions de résolution
Une action de résolution est une instance SafetySourceIssue.Action
qu'un utilisateur peut résoudre directement depuis l'écran du centre de sécurité. 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 avertit le Centre de sécurité une fois terminé.
Pour implémenter des actions de résolution, la source du centre de sécurité peut utiliser un service si l'opération est censée prendre un certain temps (PendingIntent.getService
) ou un broadcast receiver (PendingIntent.getBroadcast
).
Utilisez ce code pour envoyer un problème résolu au Centre de sécurité:
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 refus de signalement
Vous pouvez spécifier une instance PendingIntent
pouvant être déclenchée lorsqu'une instance SafetySourceIssue
est ignorée. Le Centre de sécurité gère les refus de problèmes suivants:
- Si une source envoie un problème, un utilisateur peut le fermer sur l'écran du Centre de sécurité en appuyant sur le bouton de fermeture (un bouton X sur la fiche d'avertissement).
- Lorsqu'un utilisateur ignore un problème, s'il persiste, il ne s'affiche plus dans l'interface utilisateur.
- Les refus persistants sur un disque restent lors des redémarrages de l'appareil.
- Si la source du Centre de sécurité cesse de signaler un problème, puis le signale à nouveau ultérieurement, le problème réapparaît. Cela permet de gérer les situations où un utilisateur voit un avertissement, le ferme, puis prend une mesure qui devrait atténuer le problème, mais que l'utilisateur recommence à faire quelque chose qui provoque un problème similaire. À ce stade, la fiche d'avertissement devrait réapparaître.
- Les fiches d'avertissement jaune et rouge réapparaissent tous les 180 jours, sauf si l'utilisateur les a ignorées plusieurs fois.
La source ne devrait pas avoir besoin de comportements supplémentaires, sauf dans les cas suivants:
- La source tente d'implémenter ce comportement différemment, par exemple, en ne réexécutant jamais le problème.
- La source tente de l'utiliser comme rappel, par exemple pour consigner les informations.
Fournir des données pour plusieurs utilisateurs/profils
L'API SafetyCenterManager
peut être utilisée par tous les utilisateurs et tous les profils. Pour en savoir plus, consultez la section Créer des applications multi-utilisateurs. L'objet Context
qui fournit SafetyCenterManager
est associé à une instance UserHandle
. L'instance SafetyCenterManager
renvoyée interagit donc avec le centre de sécurité 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 comment passer 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 disposer de plusieurs profils gérés. Le Centre de sécurité 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, ce qui suit se produit:
- 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 parent du profil et tous les profils gérés associés. Le broadcast receiver associé est démarré pour chaque profil et peut fournir les données associées directement à
SafetyCenterManager
sans avoir à effectuer d'appel interprofil, sauf si le broadcast receiver ou l'application estsingleUser
.La source doit fournir des données pour l'utilisateur et tous ses profils gérés. Les données de chaque entrée de l'UI peuvent varier en fonction du profil.
Tests
pourSafetyCenterManager
. Pour en savoir plus sur le test de vos interactions avec SafetyCenterManager
dans une JVM, consultez la section Ombres.
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 d'autres tests de bout en bout (E2E), mais cela n'entre pas dans le champ d'application de ce guide. Pour en savoir plus sur l'écriture de ces tests E2E, consultez la section Tests CTS (CtsSafetyCenterTestCases).
API de test et internes
Les API internes et les API de test sont destinées à un usage interne. Elles ne sont donc pas décrites en détail dans ce guide. Toutefois, nous pourrons étendre certaines API internes à l'avenir pour permettre aux OEM de créer leur propre UI. Nous mettrons à jour ce guide pour vous expliquer comment les utiliser.
Autorisations
MANAGE_SAFETY_CENTER
internal|installer|role
- Utilisé pour les API internes du Centre de sécurité
- Accordé uniquement à PermissionController et au shell
Application Paramètres
Redirection vers le 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 l'avez modifiée, vous devrez peut-être personnaliser l'accès au Centre de sécurité.
Lorsque le Centre de sécurité est activé:
- Code de l'ancienne entrée Confidentialité masquée
- L'ancien code de sécurité est masqué
- Nouvelle entrée Sécurité et confidentialité ajoutée code
- La nouvelle entrée Sécurité et confidentialité redirige vers le code du Centre de sécurité
- Les actions d'intent
android.settings.PRIVACY_SETTINGS
etandroid.settings.SECURITY_SETTINGS
sont redirigées vers l'ouverture du Centre de sécurité (code : security, privacy)
Pages sur la sécurité et la confidentialité avancées
L'application Paramètres contient des paramètres supplémentaires sous les titres Autres paramètres de sécurité et Autres paramètres de confidentialité, disponibles dans le Centre de sécurité:
Code de sécurité avancé
Code de confidentialité avancé
À partir d'Android 14, les pages des paramètres de sécurité et de confidentialité avancés sont fusionnées sur une seule page "Sécurité et confidentialité renforcées" avec l'action d'intent
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
.
Sources de sécurité
Le Centre de sécurité s'intègre à un ensemble spécifique de sources de sécurité fournies par l'application Paramètres:
- Une source de sécurité de l'écran de verrouillage vérifie qu'un écran de verrouillage est configuré avec un code secret (ou une autre mesure de sécurité) pour s'assurer que les informations privées de l'utilisateur sont protégées contre tout accès externe.
- Une source de sécurité biométrique (cachée par défaut) s'affiche pour s'intégrer à un capteur d'empreinte digitale ou de reconnaissance faciale.
Le code source de ces sources du centre de sécurité est accessible via la recherche de code Android. Si l'application Paramètres n'est pas modifiée (aucun changement n'est apporté au nom du package, au code source ou au code source qui gère un écran de verrouillage et les données biométriques), cette intégration devrait fonctionner dès la sortie de la boîte. Sinon, certaines modifications peuvent être nécessaires, comme la modification du fichier de configuration pour modifier le nom du package de l'application Paramètres et des sources qui s'intègrent à Safety Center, ainsi que l'intégration. Pour en savoir plus, consultez Modifier le fichier de configuration et les paramètres d'intégration.
À propos de PendingIntent
Si vous vous appuyez sur l'intégration existante du Centre de sécurité de l'application Paramètres sous Android 14 ou version ultérieure, le bug décrit ci-dessous a été corrigé. Dans ce cas, vous n'avez pas besoin de lire cette section.
Lorsque vous êtes sûr que le bug 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 le correctif dans le centre de sécurité.
Solution de contournement pour PendingIntent
Ce bug est causé par les paramètres qui utilisent des extras d'instance Intent
pour déterminer le fragment à ouvrir. Étant donné que Intent#equals
ne prend pas en compte les extras de l'instance Intent
, l'instance PendingIntent
de l'icône du menu en forme de roue dentée et de l'entrée sont considérées comme égales et accèdent à la même UI (même si elles sont destinées à accéder à une UI différente). Ce problème est résolu dans une version QPR en différenciant les instances PendingIntent
par code de requête. Vous pouvez également différencier cela à l'aide de Intent#setId
.
Sources de sécurité internes
Certaines sources du centre de sécurité sont internes et implémentées dans l'application système PermissionController dans le module PermissionController. Ces sources se comportent comme des sources Safety Center standards 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évocation automatique des autorisations des applications inutilisées
- Accès à la position
- Outil d'écoute des notifications
- Infos sur les règles professionnelles