Redirigir al centro de seguridad
Cualquier aplicación puede abrir el Centro de seguridad usando la acción android.content.Intent.ACTION_SAFETY_CENTER
(valor de cadena android.intent.action.SAFETY_CENTER
).
Para abrir el Centro de seguridad, realice una llamada desde una instancia Activity
:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
startActivity(openSafetyCenterIntent);
Redirigir a un problema específico
También es posible redirigir a una tarjeta de advertencia específica del Centro de seguridad utilizando extras de intención específicos. Estos extras no están destinados a ser utilizados por terceros, por lo que forman parte de SafetyCenterManager
, que forma parte de @SystemApi
. Sólo las aplicaciones del sistema pueden acceder a estos extras.
Extras de intención que redirigen una tarjeta de advertencia específica:
-
EXTRA_SAFETY_SOURCE_ID
- Valor de cadena:
android.safetycenter.extra.SAFETY_SOURCE_ID
- Tipo de cadena: especifica el ID de la fuente de seguridad de la tarjeta de advertencia asociada.
- Requerido para que funcione la redirección al problema
- Valor de cadena:
-
EXTRA_SAFETY_SOURCE_ISSUE_ID
- Valor de cadena:
android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
- Tipo de cadena: especifica el ID de la tarjeta de advertencia.
- Requerido para que funcione la redirección al problema
- Valor de cadena:
-
EXTRA_SAFETY_SOURCE_USER_HANDLE
- Valor de cadena:
android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
- Tipo
UserHandle
: especificaUserHandle
para la tarjeta de advertencia asociada. - Opcional (el valor predeterminado es el usuario actual)
- Valor de cadena:
El siguiente fragmento de código se puede utilizar desde una instancia Activity
para abrir la pantalla del Centro de seguridad a un problema específico:
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);
Redirigir a una subpágina específica (a partir de Android 14)
En Android 14 o superior, la página del Centro de seguridad se divide en varias subpáginas que representan los diferentes SafetySourcesGroup
(en Android 13, esto se muestra como entradas plegables).
Es posible redirigir a una subpágina específica utilizando este intent extra:
-
EXTRA_SAFETY_SOURCES_GROUP_ID
- Valor de cadena:
android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
- Tipo de cadena: especifica el ID de
SafetySourcesGroup
- Requerido para que funcione la redirección a la subpágina
- Valor de cadena:
El siguiente fragmento de código se puede utilizar desde una instancia Activity
para abrir la pantalla del Centro de seguridad en una subpágina específica:
Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");
startActivity(openSafetyCenterIntent);
Utilice las API de origen del Centro de seguridad
Las API de origen del Centro de seguridad están disponibles mediante SafetyCenterManager
(que es @SystemApi
). El código para la superficie API está disponible en Búsqueda de código . El código de implementación de las API está disponible en Code Search .
Permisos
Solo las aplicaciones del sistema incluidas en la lista permitida que utilizan los permisos que se enumeran a continuación pueden acceder a las API de origen del Centro de seguridad. Para obtener información adicional, consulte Lista de permitidos de permisos privilegiados .
-
READ_SAFETY_CENTER_STATUS
-
signature|privileged
- Se utiliza para la API
SafetyCenterManager#isSafetyCenterEnabled()
(no es necesario para las fuentes del Centro de seguridad, solo necesitan el permisoSEND_SAFETY_CENTER_UPDATE
) - Utilizado por aplicaciones del sistema que verifican si el Centro de seguridad está habilitado
- Otorgado solo a aplicaciones del sistema incluidas en la lista permitida
-
-
SEND_SAFETY_CENTER_UPDATE
-
internal|privileged
- Se utiliza para la API habilitada y la API de fuentes de seguridad.
- Utilizado únicamente por fuentes de seguridad.
- Otorgado solo a aplicaciones del sistema incluidas en la lista permitida
-
Estos permisos son privilegiados y puede adquirirlos solo agregándolos al archivo relevante, por ejemplo, el archivo com.android.settings.xml
para la aplicación Configuración y al archivo AndroidManifest.xml
de la aplicación. Consulte protectionLevel
para obtener más información sobre el modelo de permiso.
Obtenga el SafetyCenterManager
SafetyCenterManager
es una clase @SystemApi
a la que se puede acceder desde aplicaciones del sistema a partir de Android 13. Esta llamada demuestra cómo obtener 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;
}
Compruebe si el Centro de seguridad está habilitado
Esta llamada verifica si el Centro de seguridad está habilitado. La llamada requiere el permiso READ_SAFETY_CENTER_STATUS
o SEND_SAFETY_CENTER_UPDATE
:
boolean isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled();
if (isSafetyCenterEnabled) {
// …
} else {
// …
}
Proveer información
Los datos de origen del Centro de seguridad con el String sourceId
proporcionado se proporcionan al Centro de seguridad con el objeto SafetySourceData
, que representa una entrada de la interfaz de usuario y una lista de problemas (tarjetas de advertencia). La entrada de la interfaz de usuario y las tarjetas de advertencia pueden tener diferentes niveles de gravedad especificados en la clase SafetySourceData
:
-
SEVERITY_LEVEL_UNSPECIFIED
- No se especifica gravedad
- Color: Gris o transparente (dependiendo del
SafetySourcesGroup
de la entrada) - Se utiliza para datos dinámicos que se presentan como una entrada estática en la interfaz de usuario o para mostrar una entrada no especificada.
- No debe usarse para tarjetas de advertencia.
-
SEVERITY_LEVEL_INFORMATION
- Información básica o sugerencia menor.
- Color verde
-
SEVERITY_LEVEL_RECOMMENDATION
- Recomendación de que el usuario tome medidas sobre este tema, ya que podría ponerlo en riesgo
- Color amarillo
-
SEVERITY_LEVEL_CRITICAL_WARNING
- Advertencia crítica de que el usuario debe tomar medidas sobre este tema, ya que presenta un riesgo.
- Color rojo
SafetySourceData
El objeto SafetySourceData
se compone de una entrada de interfaz de usuario, tarjetas de advertencia e invariantes.
- Instancia opcional
SafetySourceStatus
(entrada de interfaz de usuario) - Lista de instancias
SafetySourceIssue
(tarjetas de advertencia) - Extras
Bundle
opcional (a partir de 14) - Invariantes:
- La lista
SafetySourceIssue
debe estar compuesta de problemas con identificadores únicos. - La instancia
SafetySourceIssue
no debe ser de mayor importancia queSafetySourceStatus
si existe (a menos queSafetySourceStatus
seaSEVERITY_LEVEL_UNSPECIFIED
, en cuyo caso se permiten problemasSEVERITY_LEVEL_INFORMATION
). - Se deben cumplir requisitos adicionales impuestos por la configuración de API; por ejemplo, si la fuente es solo para problemas, no debe proporcionar una instancia
SafetySourceStatus
.
- La lista
SafetySourceStatus
- Título
CharSequence
requerido - Resumen
CharSequence
requerido - Nivel de gravedad requerido
- Instancia opcional
PendingIntent
para redirigir al usuario a la página correcta (el valor predeterminado usaintentAction
de la configuración, si corresponde) -
IconAction
opcional (que se muestra como un ícono lateral en la entrada) compuesto por:- Tipo de icono requerido, que debe ser uno de los siguientes tipos:
-
ICON_TYPE_GEAR
: se muestra como un engranaje junto a la entrada de la interfaz de usuario. -
ICON_TYPE_INFO
: se muestra como un icono de información junto a la entrada de la interfaz de usuario.
-
- Se requiere
PendingIntent
para redirigir al usuario a otra página
- Tipo de icono requerido, que debe ser uno de los siguientes tipos:
- Valor booleano
enabled
opcional que permite marcar la entrada de la interfaz de usuario como deshabilitada, por lo que no se puede hacer clic en ella (el valor predeterminado estrue
) - Invariantes:
- Las instancias
PendingIntent
deben abrir una instanciaActivity
. - Si la entrada está deshabilitada, debe designarse
SEVERITY_LEVEL_UNSPECIFIED
. - Requisitos adicionales impuestos por la configuración de API.
- Las instancias
SafetySourceIssue
- Identificador
String
único requerido - Título
CharSequence
requerido - Subtítulo opcional
CharSequence
- Resumen
CharSequence
requerido - Nivel de gravedad requerido
- Categoría de emisión opcional, que debe ser una de:
-
ISSUE_CATEGORY_DEVICE
: el problema afecta el dispositivo del usuario. -
ISSUE_CATEGORY_ACCOUNT
: El problema afecta las cuentas del usuario. -
ISSUE_CATEGORY_GENERAL
: El problema afecta la seguridad general del usuario. Este es el valor predeterminado. -
ISSUE_CATEGORY_DATA
(a partir de Android 14): el problema afecta los datos del usuario. -
ISSUE_CATEGORY_PASSWORDS
(a partir de Android 14): el problema afecta las contraseñas del usuario. -
ISSUE_CATEGORY_PERSONAL_SAFETY
(a partir de Android 14): el problema afecta la seguridad personal del usuario.
-
- Lista de elementos
Action
que el usuario puede tomar para este problema, estando cada instanciaAction
compuesta por:- Identificador
String
único requerido - Etiqueta
CharSequence
requerida - Se requiere
PendingIntent
para redirigir al usuario a otra página o procesar la acción directamente desde la pantalla del Centro de seguridad. - Booleano opcional para especificar si este problema se puede resolver directamente desde la pantalla del Centro de seguridad (el valor predeterminado es
false
) - Mensaje de éxito
CharSequence
opcional, que se mostrará al usuario cuando el problema se resuelva exitosamente directamente desde la pantalla del Centro de seguridad
- Identificador
-
PendingIntent
opcional que se llama cuando el usuario descarta el problema (el valor predeterminado es no llamar a nada) - Requerido Identificador de tipo de problema
String
; Esto es similar al identificador de problema, pero no tiene que ser único y se usa para iniciar sesión. -
String
opcional para la identificación de deduplicación, esto permite publicar el mismoSafetySourceIssue
de diferentes fuentes y mostrarlo solo una vez en la interfaz de usuario, suponiendo que tengan el mismodeduplicationGroup
(a partir de Android 14). Si no se especifica, el problema nunca se deduplica -
CharSequence
opcional para el título de atribución, este es un texto que muestra dónde se originó la tarjeta de advertencia (a partir de Android 14). Si no se especifica, utiliza el título deSafetySourcesGroup
- Capacidad de resolución de problemas opcional (a partir de Android 14), que debe ser una de las siguientes:
-
ISSUE_ACTIONABILITY_MANUAL
: el usuario debe resolver este problema manualmente. Este es el valor predeterminado. -
ISSUE_ACTIONABILITY_TIP
: este problema es solo un consejo y es posible que no requiera ninguna intervención del usuario. -
ISSUE_ACTIONABILITY_AUTOMATIC
: este problema ya se ha solucionado y es posible que no requiera ninguna intervención del usuario.
-
- Comportamiento de notificación opcional (a partir de Android 14), que debe ser uno de:
-
NOTIFICATION_BEHAVIOR_UNSPECIFIED
: El Centro de seguridad decidirá si se necesita una notificación para la tarjeta de advertencia. Este es el valor predeterminado. -
NOTIFICATION_BEHAVIOR_NEVER
: No se publica ninguna notificación. -
NOTIFICATION_BEHAVIOR_DELAYED
: se publica una notificación algún tiempo después de que se informa el problema por primera vez. -
NOTIFICATION_BEHAVIOR_IMMEDIATELY
: se publica una notificación tan pronto como se informa el problema.
-
-
Notification
opcional, para mostrar una notificación personalizada con la tarjeta de advertencia (a partir de Android 14). Si no se especifica, laNotification
se deriva de la tarjeta de advertencia. Compuesto de:- Título
CharSequence
requerido - Resumen
CharSequence
requerido - Lista de elementos
Action
que el usuario puede realizar para esta notificación
- Título
- Invariantes:
- La lista de instancias
Action
debe estar compuesta de acciones con identificadores únicos. - La lista de instancias
Action
debe contener uno o dos elementosAction
. Si la capacidad de acción no esISSUE_ACTIONABILITY_MANUAL
, se permite tener ceroAction
. - El OnDismiss
PendingIntent
no debe abrir una instanciaActivity
- Requisitos adicionales impuestos por la configuración API
- La lista de instancias
Los datos se proporcionan sobre ciertos eventos al Centro de seguridad, por lo que es necesario especificar qué causó que la fuente proporcionara SafetySourceData
una instancia SafetyEvent
.
SafetyEvent
- Tipo requerido, que debe ser uno de:
-
SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
: El estado de la fuente ha cambiado. -
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
: Respondiendo a una señal de actualización/reexploración del Centro de seguridad; use esto en lugar deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
para que Safety Center pueda realizar un seguimiento de la solicitud de actualización/rescaneo. -
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
: ResolvimosSafetySourceIssue.Action
directamente desde la pantalla del Centro de seguridad; use esto en lugar deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
para que Safety Center pueda realizar un seguimiento delSafetySourceIssue.Action
que se está resolviendo. -
SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
: Intentamos resolverSafetySourceIssue.Action
directamente desde la pantalla del Centro de seguridad, pero no pudimos hacerlo; use esto en lugar deSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
para que Safety Center pueda rastrear el errorSafetySourceIssue.Action
. -
SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED
: el idioma del dispositivo ha cambiado, por lo que estamos actualizando el texto de los datos proporcionados; está permitido usarSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
para esto. -
SAFETY_EVENT_TYPE_DEVICE_REBOOTED
: proporcionamos estos datos como parte de un inicio inicial, ya que los datos del Centro de seguridad no persisten durante los reinicios; está permitido usarSAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
para esto.
-
- Identificador
String
opcional para el ID de transmisión de actualización. - Identificador
String
opcional para la instanciaSafetySourceIssue
que se resuelve. - Identificador
String
opcional para la instanciaSafetySourceIssue.Action
que se resuelve. - Invariantes:
- Se debe proporcionar el ID de transmisión de actualización si el tipo es
SAFETY_EVENT_TYPE_REFRESH_REQUESTED
- Se deben proporcionar los ID del problema y la acción si el tipo es
SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED
oSAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
- Se debe proporcionar el ID de transmisión de actualización si el tipo es
A continuación se muestra un ejemplo de cómo una fuente podría proporcionar datos al Centro de seguridad (en este caso, proporciona una entrada con una única tarjeta de advertencia):
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);
Obtener los últimos datos proporcionados
Puede obtener los últimos datos proporcionados al Centro de seguridad para una fuente propiedad de su aplicación. Puede usar esto para mostrar algo en su propia interfaz de usuario, para verificar si es necesario actualizar los datos antes de realizar una operación costosa o para proporcionar la misma instancia SafetySourceData
al Centro de seguridad con algunos cambios o con una nueva instancia SafetyEvent
. También es útil para realizar pruebas.
Utilice este código para obtener los últimos datos proporcionados al Centro de seguridad:
SafetySourceData lastDataProvided = safetyCenterManager.getSafetySourceData("MySourceId");
Informar un error
Si no puede recopilar datos SafetySourceData
, puede informar el error al Centro de seguridad, que cambia la entrada a gris, borra los datos almacenados en caché y proporciona un mensaje parecido a No se pudo verificar la configuración . También puede informar un error si una instancia de SafetySourceIssue.Action
no se resuelve, en cuyo caso los datos almacenados en caché no se borran y la entrada de la interfaz de usuario no se modifica; pero aparece un mensaje al usuario para informarle que algo salió mal.
Puede proporcionar el error utilizando SafetySourceErrorDetails
, que se compone de:
-
SafetySourceErrorDetails
: InstanciaSafetyEvent
requerida :
// 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);
Responder a una solicitud de actualización o reexploración
Puede recibir una señal del Centro de seguridad para proporcionar nuevos datos. Responder a una solicitud de actualización o reescaneo garantiza que el usuario vea el estado actual al abrir el Centro de seguridad y cuando toque el botón de escaneo.
Esto se hace recibiendo una transmisión con la siguiente acción:
-
ACTION_REFRESH_SAFETY_SOURCES
- Valor de cadena:
android.safetycenter.action.REFRESH_SAFETY_SOURCES
- Se activa cuando el Centro de seguridad envía una solicitud para actualizar los datos de la fuente de seguridad para una aplicación determinada.
- Intento protegido que solo puede ser enviado por el sistema
- Se envía a todas las fuentes de seguridad en el archivo de configuración como intención explícita y requiere el permiso
SEND_SAFETY_CENTER_UPDATE
- Valor de cadena:
Los siguientes extras se proporcionan como parte de esta transmisión:
-
EXTRA_REFRESH_SAFETY_SOURCE_IDS
- Valor de cadena:
android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
- Tipo de matriz de cadena (
String[]
), representa los ID de origen que se actualizarán para la aplicación determinada
- Valor de cadena:
EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Valor de cadena:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
- Tipo entero, representa un tipo de solicitud
@IntDef
- Debe ser uno de:
-
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
: solicita a la fuente que proporcione datos relativamente rápido, normalmente cuando el usuario abre la página. -
EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA
: solicita a la fuente que proporcione datos lo más actualizados posible, generalmente cuando el usuario presiona el botón de volver a escanear.
-
- Valor de cadena:
EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Valor de cadena:
android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
- Tipo de cadena, representa un identificador único para la actualización solicitada
- Valor de cadena:
Para recibir una señal del Centro de seguridad, implemente una instancia BroadcastReceiver
. La transmisión se envía con BroadcastOptions
especiales que permiten al receptor iniciar un servicio en primer plano.
BroadcastReceiver
responde a una solicitud de actualización:
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 misma instancia de BroadcastReceiver
en el ejemplo anterior se declara en 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, una fuente de Safety Center se implementa de tal manera que llame SafetyCenterManager
cuando cambien sus datos. Por razones de salud del sistema, recomendamos responder solo a la señal de volver a escanear (cuando el usuario toca el botón de escaneo) y no cuando el usuario abre el Centro de seguridad. Si se requiere esta funcionalidad, se debe configurar el campo refreshOnPageOpenAllowed="true"
en el archivo de configuración para que la fuente reciba la transmisión entregada en estos casos.
Responder al Centro de seguridad cuando esté habilitado o deshabilitado
Puede responder cuando el Centro de seguridad está habilitado o deshabilitado mediante esta acción de intención:
-
ACTION_SAFETY_CENTER_ENABLED_CHANGED
- Valor de cadena:
android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
- Se activa cuando el Centro de seguridad está habilitado o deshabilitado mientras el dispositivo está en ejecución
- No se llama al arrancar (use
ACTION_BOOT_COMPLETED
para eso) - Intento protegido que solo puede ser enviado por el sistema
- Enviado a todas las fuentes de seguridad en el archivo de configuración como una intención explícita, requiere el permiso
SEND_SAFETY_CENTER_UPDATE
- Enviado como una intención implícita que requiere el permiso
READ_SAFETY_CENTER_STATUS
- Valor de cadena:
Esta acción de intención es útil para habilitar o deshabilitar funciones relacionadas con el Centro de seguridad en el dispositivo.
Implementar acciones resolutivas
Una acción de resolución es una instancia SafetySourceIssue.Action
que un usuario puede resolver directamente desde la pantalla del Centro de seguridad. El usuario toca un botón de acción y se activa la instancia PendingIntent
en SafetySourceIssue.Action
enviada por la fuente de seguridad, lo que resuelve el problema en segundo plano y notifica al Centro de seguridad cuando termina.
Para implementar acciones de resolución, la fuente del Centro de seguridad puede usar un servicio si se espera que la operación demore algún tiempo ( PendingIntent.getService
) o un receptor de transmisión ( PendingIntent.getBroadcast
).
Utilice este código para enviar un problema de resolución al Centro de seguridad:
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
resuelve la acción:
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 misma instancia de BroadcastReceiver
en el ejemplo anterior se declara en 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>
Responder a los despidos
Puede especificar una instancia PendingIntent
que se puede activar cuando se descarta una instancia SafetySourceIssue
. El Centro de Seguridad maneja estos despidos por problemas:
- Si una fuente informa un problema, un usuario puede descartarlo en la pantalla del Centro de seguridad tocando el botón descartar (un botón X en la tarjeta de advertencia).
- Cuando un usuario descarta un problema, si el problema continúa, no volverá a aparecer en la interfaz de usuario.
- Los despidos persistentes en un disco permanecen durante los reinicios del dispositivo.
- Si la fuente del Centro de seguridad deja de proporcionar un problema y luego lo vuelve a proporcionar más adelante, el problema vuelve a surgir. Esto es para permitir situaciones en las que un usuario ve una advertencia, la descarta y luego toma medidas que deberían aliviar el problema, pero luego el usuario vuelve a hacer algo que causa un problema similar. En este punto, la tarjeta de advertencia debería resurgir.
- Las tarjetas de advertencia amarillas y rojas reaparecen cada 180 días, a menos que el usuario las haya ignorado varias veces.
La fuente no debería necesitar comportamientos adicionales a menos que:
- La fuente intenta implementar este comportamiento de manera diferente, por ejemplo, nunca resurgir el problema.
- La fuente intenta utilizar esto como devolución de llamada, por ejemplo, para registrar la información.
Proporcionar datos para múltiples usuarios/perfiles
La API SafetyCenterManager
se puede utilizar entre usuarios y perfiles. Para obtener más información, consulte Creación de aplicaciones multiusuario . El objeto Context
que proporciona SafetyCenterManager
está asociado con una instancia UserHandle
, por lo que la instancia SafetyCenterManager
devuelta interactúa con el Centro de seguridad para esa instancia UserHandle
. De forma predeterminada, Context
está asociado con el usuario que ejecuta, pero es posible crear una instancia para otro usuario si la aplicación tiene los permisos INTERACT_ACROSS_USERS
e INTERACT_ACROSS_USERS_FULL
. Este ejemplo muestra cómo realizar una llamada entre usuarios/perfiles:
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
Cada usuario del dispositivo puede tener varios perfiles administrados. El Centro de seguridad proporciona datos diferentes para cada usuario, pero fusiona los datos de todos los perfiles administrados asociados con un usuario determinado.
Cuando se establece profile="all_profiles"
para la fuente en el archivo de configuración, ocurre lo siguiente:
- Hay una entrada de interfaz de usuario para el usuario (perfil principal) y todos sus perfiles administrados asociados (que usan instancias
titleForWork
). La señal de actualización o reexploración se envía para el perfil principal y todos los perfiles administrados asociados. El receptor asociado se inicia para cada perfil y puede proporcionar los datos asociados directamente a
SafetyCenterManager
sin tener que realizar una llamada entre perfiles a menos que el receptor o la aplicación seasingleUser
.Se espera que la fuente proporcione datos para el usuario y todos sus perfiles administrados. Los datos de cada entrada de la interfaz de usuario pueden ser diferentes según el perfil.
Pruebas
puede acceder ShadowSafetyCenterManager
y utilizarlo en una prueba 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);
}
Puede escribir más pruebas de un extremo a otro (E2E), pero eso está fuera del alcance de esta guía. Para obtener más información sobre cómo escribir estas pruebas E2E, consulte Pruebas CTS (CtsSafetyCenterTestCases)
API de prueba y internas
Las API internas y las API de prueba son para uso interno, por lo que no se describen en detalle en esta guía. Sin embargo, es posible que ampliemos algunas API internas en el futuro para permitir que los OEM creen su propia interfaz de usuario y actualizaremos esta guía para brindar orientación sobre cómo usarlas.
Permisos
-
MANAGE_SAFETY_CENTER
-
internal|installer|role
- Se utiliza para las API internas del Centro de seguridad
- Sólo concedido a PermissionController y Shell
-
Aplicación de configuración
Redirección del centro de seguridad
De forma predeterminada, se accede al Centro de seguridad a través de la aplicación Configuración con una nueva entrada de Seguridad y privacidad . Si usa una aplicación de Configuración diferente o si modificó la aplicación de Configuración, es posible que deba personalizar cómo se accede al Centro de seguridad.
Cuando el Centro de seguridad está habilitado:
- La entrada de privacidad heredada es un código oculto
- La entrada de seguridad heredada es un código oculto
- Se agrega un nuevo código de entrada de Seguridad y privacidad
- La nueva entrada de Seguridad y privacidad redirige al código del Centro de seguridad
- Las acciones de intención
android.settings.PRIVACY_SETTINGS
yandroid.settings.SECURITY_SETTINGS
se redirigen para abrir el Centro de seguridad (código: seguridad , privacidad ).
Páginas avanzadas de seguridad y privacidad
La aplicación Configuración contiene configuraciones adicionales en Más configuraciones de seguridad y Más títulos de configuraciones de privacidad , disponibles en el Centro de seguridad:
Código de seguridad avanzado
Código de privacidad avanzado
A partir de Android 14, la página de configuración avanzada de seguridad y privacidad se fusiona en una única página "Más seguridad y privacidad" con la acción de intención
"com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
Fuentes de seguridad
Safety Center se integra con un conjunto específico de fuentes de seguridad proporcionadas por la aplicación Configuración:
- Una fuente de seguridad de la pantalla de bloqueo verifica que la pantalla de bloqueo esté configurada con un código de acceso (u otro tipo de seguridad) para garantizar que la información privada del usuario se mantenga a salvo del acceso externo.
- Aparece una fuente de seguridad biométrica (oculta de forma predeterminada) para integrarse con un sensor facial o de huellas dactilares.
Se puede acceder al código fuente de estas fuentes del Centro de seguridad mediante la búsqueda de código de Android . Si la aplicación Configuración no se modifica (no se realizan cambios en el nombre del paquete, el código fuente o el código fuente que trata con una pantalla de bloqueo y datos biométricos), entonces esta integración debería funcionar de inmediato. De lo contrario, es posible que se requieran algunas modificaciones, como cambiar el archivo de configuración para cambiar el nombre del paquete de la aplicación Configuración y las fuentes que se integran con Safety Center, así como la integración. Para obtener más información, consulte Actualizar el archivo de configuración y los ajustes de integración .
Acerca de la intención pendiente
Si confía en la integración existente del Centro de seguridad de la aplicación Configuración en Android 14 o superior, se solucionó el error que se describe a continuación. En este caso no es necesario leer esta sección.
Cuando esté seguro de que el error no existe, establezca un valor de configuración de recurso booleano XML en la aplicación Configuración config_isSafetyCenterLockScreenPendingIntentFixed
en true
para desactivar la solución alternativa dentro del Centro de seguridad.
Solución alternativa de intención pendiente
Este error se debe a que la Configuración utiliza extras de instancia Intent
para determinar qué fragmento abrir. Debido a que Intent#equals
no tiene en cuenta los extras de la instancia Intent
, la instancia PendingIntent
para el icono del menú de ajustes y la entrada se consideran iguales y navegan a la misma interfaz de usuario (aunque estén destinadas a navegar a una interfaz de usuario diferente). Este problema se solucionó en una versión de QPR al diferenciar las instancias PendingIntent
por código de solicitud. Alternativamente, esto podría diferenciarse usando Intent#setId
.
Fuentes de seguridad internas
Algunas fuentes del Centro de seguridad son internas y se implementan en la aplicación del sistema PermissionController dentro del módulo PermissionController. Estas fuentes se comportan como fuentes habituales del Centro de seguridad y no reciben ningún tratamiento especial. El código de estas fuentes está disponible a través de la búsqueda de códigos de Android .
Se trata principalmente de señales de privacidad, por ejemplo:
- Accesibilidad
- Revocar automáticamente aplicaciones no utilizadas
- Acceso a la ubicación
- Oyente de notificaciones
- Información de política laboral