Compartir a través de


Agente de escucha de notificaciones: acceso a todas las notificaciones

El agente de escucha de notificaciones proporciona acceso a las notificaciones de un usuario. Los relojes inteligentes y otros ponibles pueden usar el agente de escucha de notificaciones para enviar las notificaciones del teléfono al dispositivo portátil. Las aplicaciones de automatización del hogar pueden usar el agente de escucha de notificaciones para realizar acciones específicas cuando se reciben notificaciones, como hacer que las luces parpadeen cuando reciba una llamada.

Importante

Requiere actualización de aniversario: debe tener como destino el SDK 14393 y ejecutar la compilación 14393 o posterior para usar el agente de escucha de notificaciones.

API importantes: Clase UserNotificationListener, Clase UserNotificationChangedTrigger

Habilitar el agente de escucha agregando la funcionalidad De notificación de usuario

Para usar el agente de escucha de notificaciones, debes agregar la funcionalidad Agente de escucha de notificación de usuario al manifiesto de la aplicación.

  1. En Visual Studio, en el Explorador de soluciones, haga doble clic en Package.appxmanifest el archivo para abrir el diseñador de manifiestos.
  2. Abra la pestaña Funcionalidades.
  3. Compruebe la funcionalidad Agente de escucha de notificaciones de usuario.

Compruebe si se admite el agente de escucha.

Si la aplicación admite versiones anteriores de Windows 10, debes usar la clase ApiInformation para comprobar si se admite el agente de escucha. Si no se admite el agente de escucha, evite ejecutar ninguna llamada a las API del agente de escucha.

if (ApiInformation.IsTypePresent("Windows.UI.Notifications.Management.UserNotificationListener"))
{
    // Listener supported!
}
 
else
{
    // Older version of Windows, no Listener
}

Solicitud de acceso al agente de escucha

Dado que el agente de escucha permite el acceso a las notificaciones del usuario, los usuarios deben conceder permiso a la aplicación para acceder a sus notificaciones. Durante la experiencia de primera ejecución de la aplicación, debes solicitar acceso para usar el agente de escucha de notificaciones. Si lo desea, puede mostrar una interfaz de usuario preliminar que explique por qué la aplicación necesita acceso a las notificaciones del usuario antes de llamar a RequestAccessAsync, para que el usuario comprenda por qué deben permitir el acceso.

// Get the listener
UserNotificationListener listener = UserNotificationListener.Current;
 
// And request access to the user's notifications (must be called from UI thread)
UserNotificationListenerAccessStatus accessStatus = await listener.RequestAccessAsync();
 
switch (accessStatus)
{
    // This means the user has granted access.
    case UserNotificationListenerAccessStatus.Allowed:
 
        // Yay! Proceed as normal
        break;
 
    // This means the user has denied access.
    // Any further calls to RequestAccessAsync will instantly
    // return Denied. The user must go to the Windows settings
    // and manually allow access.
    case UserNotificationListenerAccessStatus.Denied:
 
        // Show UI explaining that listener features will not
        // work until user allows access.
        break;
 
    // This means the user closed the prompt without
    // selecting either allow or deny. Further calls to
    // RequestAccessAsync will show the dialog again.
    case UserNotificationListenerAccessStatus.Unspecified:
 
        // Show UI that allows the user to bring up the prompt again
        break;
}

El usuario puede revocar el acceso en cualquier momento a través de la configuración de Windows. Por lo tanto, la aplicación siempre debe comprobar el estado de acceso a través del método GetAccessStatus antes de ejecutar el código que usa el agente de escucha de notificaciones. Si el usuario revoca el acceso, las API producirán un error en modo silencioso en lugar de iniciar una excepción (por ejemplo, la API para obtener todas las notificaciones simplemente devolverá una lista vacía).

Acceso a las notificaciones del usuario

Con el agente de escucha de notificaciones, puede obtener una lista de las notificaciones actuales del usuario. Simplemente llame al método GetNotificationsAsync y especifique el tipo de notificaciones que desea obtener (actualmente, el único tipo de notificaciones admitidas son notificaciones del sistema).

// Get the toast notifications
IReadOnlyList<UserNotification> notifs = await listener.GetNotificationsAsync(NotificationKinds.Toast);

Mostrar las notificaciones

Cada notificación se representa como UserNotification, que proporciona información sobre la aplicación desde la que procede la notificación, la hora en que se creó la notificación, el identificador de la notificación y la propia notificación.

public sealed class UserNotification
{
    public AppInfo AppInfo { get; }
    public DateTimeOffset CreationTime { get; }
    public uint Id { get; }
    public Notification Notification { get; }
}

La propiedad AppInfo proporciona la información necesaria para mostrar la notificación.

Nota:

Se recomienda rodear todo el código para procesar una sola notificación en un try/catch, en caso de que se produzca una excepción inesperada al capturar una sola notificación. No debería mostrar completamente otras notificaciones solo debido a un problema con una notificación específica.

// Select the first notification
UserNotification notif = notifs[0];
 
// Get the app's display name
string appDisplayName = notif.AppInfo.DisplayInfo.DisplayName;
 
// Get the app's logo
BitmapImage appLogo = new BitmapImage();
RandomAccessStreamReference appLogoStream = notif.AppInfo.DisplayInfo.GetLogo(new Size(16, 16));
await appLogo.SetSourceAsync(await appLogoStream.OpenReadAsync());

El contenido de la notificación en sí, como el texto de la notificación, se encuentra en la propiedad Notification . Esta propiedad contiene la parte visual de la notificación. (Si está familiarizado con el envío de notificaciones en Windows, observará que Las propiedades Visual y Visual.Bindings del objeto Notification corresponden a lo que los desarrolladores envían al extraer una notificación).

Queremos buscar el enlace del sistema (para el código de prueba de errores, debe comprobar que el enlace no es null). Desde el enlace, puede obtener los elementos de texto. Puede elegir mostrar tantos elementos de texto como desee. (Lo ideal es que se muestren todos). Puede optar por tratar los elementos de texto de forma diferente; por ejemplo, trate el primero como texto de título y los elementos posteriores como texto del cuerpo.

// Get the toast binding, if present
NotificationBinding toastBinding = notif.Notification.Visual.GetBinding(KnownNotificationBindings.ToastGeneric);
 
if (toastBinding != null)
{
    // And then get the text elements from the toast binding
    IReadOnlyList<AdaptiveNotificationText> textElements = toastBinding.GetTextElements();
 
    // Treat the first text element as the title text
    string titleText = textElements.FirstOrDefault()?.Text;
 
    // We'll treat all subsequent text elements as body text,
    // joining them together via newlines.
    string bodyText = string.Join("\n", textElements.Skip(1).Select(t => t.Text));
}

Eliminación de una notificación específica

Si su dispositivo portátil o servicio permite al usuario descartar las notificaciones, puede quitar la notificación real para que el usuario no lo vea más adelante en su teléfono o PC. Simplemente proporcione el identificador de notificación (obtenido del objeto UserNotification ) de la notificación que desea quitar:

// Remove the notification
listener.RemoveNotification(notifId);

Borrar todas las notificaciones

El método UserNotificationListener.ClearNotifications borra todas las notificaciones del usuario. Use este método con precaución. Solo debe borrar todas las notificaciones si su dispositivo portátil o servicio muestra TODAS las notificaciones. Si su dispositivo portátil o servicio solo muestra determinadas notificaciones, cuando el usuario hace clic en el botón "Borrar notificaciones", el usuario solo espera que se quiten esas notificaciones específicas; Sin embargo, llamar al método ClearNotifications realmente provocaría que se quitaran todas las notificaciones, incluidas las que no mostraba el dispositivo portátil o el servicio.

// Clear all notifications. Use with caution.
listener.ClearNotifications();

Tarea en segundo plano para la notificación agregada o descartada

Una manera habitual de permitir que una aplicación escuche las notificaciones es configurar una tarea en segundo plano, de modo que puedas saber cuándo se agregó o descarta una notificación independientemente de si la aplicación se está ejecutando actualmente.

Gracias al modelo de proceso único agregado en la actualización de aniversario, agregar tareas en segundo plano es bastante simple. En el código de la aplicación principal, después de haber obtenido el acceso del usuario al agente de escucha de notificaciones y obtenido acceso para ejecutar tareas en segundo plano llamando a UserNotificationListener.Current.RequestAccessAsync y BackgroundExecutionManager.RequestAccessAsync respectivamente, simplemente registre una nueva tarea en segundo plano y establezca UserNotificationChangedTrigger mediante el tipo de notificación del sistema.

// TODO: Request/check Listener access via UserNotificationListener.Current.RequestAccessAsync
 
// TODO: Request/check background task access via BackgroundExecutionManager.RequestAccessAsync
 
// If background task isn't registered yet
if (!BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals("UserNotificationChanged")))
{
    // Specify the background task
    var builder = new BackgroundTaskBuilder()
    {
        Name = "UserNotificationChanged"
    };
 
    // Set the trigger for Listener, listening to Toast Notifications
    builder.SetTrigger(new UserNotificationChangedTrigger(NotificationKinds.Toast));
 
    // Register the task
    builder.Register();
}

A continuación, en el App.xaml.cs, invalide el método OnBackgroundActivated si aún no lo ha hecho y usa una instrucción switch en el nombre de la tarea para determinar cuál de los muchos desencadenadores de tareas en segundo plano se invocó.

protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
    var deferral = args.TaskInstance.GetDeferral();
 
    switch (args.TaskInstance.Task.Name)
    {
        case "UserNotificationChanged":
            // Call your own method to process the new/removed notifications
            // The next section of documentation discusses this code
            await MyWearableHelpers.SyncNotifications();
            break;
    }
 
    deferral.Complete();
}

La tarea en segundo plano es simplemente una "pulsación de hombro": no proporciona información sobre qué notificación específica se ha agregado o quitado. Cuando se desencadene la tarea en segundo plano, debe sincronizar las notificaciones en su dispositivo portátil para que reflejen las notificaciones en la plataforma. Esto garantiza que si se produce un error en la tarea en segundo plano, las notificaciones de su dispositivo portátil se pueden recuperar la próxima vez que se ejecute la tarea en segundo plano.

SyncNotifications es un método que implementa; en la sección siguiente se muestra cómo.

Determinar qué notificaciones se agregaron y quitaron

En el SyncNotifications método, para determinar qué notificaciones se han agregado o quitado (sincronizando notificaciones con su dispositivo portátil), debe calcular la diferencia entre la recopilación de notificaciones actual y las notificaciones de la plataforma.

// Get all the current notifications from the platform
IReadOnlyList<UserNotification> userNotifications = await listener.GetNotificationsAsync(NotificationKinds.Toast);
 
// Obtain the notifications that our wearable currently has displayed
IList<uint> wearableNotificationIds = GetNotificationsOnWearable();
 
// Copy the currently displayed into a list of notification ID's to be removed
var toBeRemoved = new List<uint>(wearableNotificationIds);
 
// For each notification in the platform
foreach (UserNotification userNotification in userNotifications)
{
    // If we've already displayed this notification
    if (wearableNotificationIds.Contains(userNotification.Id))
    {
        // We want to KEEP it displayed, so take it out of the list
        // of notifications to remove.
        toBeRemoved.Remove(userNotification.Id);
    }
 
    // Otherwise it's a new notification
    else
    {
        // Display it on the Wearable
        SendNotificationToWearable(userNotification);
    }
}
 
// Now our toBeRemoved list only contains notification ID's that no longer exist in the platform.
// So we will remove all those notifications from the wearable.
foreach (uint id in toBeRemoved)
{
    RemoveNotificationFromWearable(id);
}

Evento de primer plano para la notificación agregada o descartada

Importante

Problema conocido: en las compilaciones anteriores a la compilación 17763/octubre de 2018 Update/Versión 1809, el evento en primer plano provocará un bucle de CPU o no funcionó. Si necesita compatibilidad con esas compilaciones anteriores, use la tarea en segundo plano en su lugar.

También puede escuchar notificaciones desde un controlador de eventos en memoria...

// Subscribe to foreground event
listener.NotificationChanged += Listener_NotificationChanged;
 
private void Listener_NotificationChanged(UserNotificationListener sender, UserNotificationChangedEventArgs args)
{
    // Your code for handling the notification
}

Cómo corregir retrasos en la tarea en segundo plano

Al probar la aplicación, es posible que observe que la tarea en segundo plano a veces se retrasa y no se desencadena durante varios minutos. Para corregir el retraso, pida al usuario que vaya a la configuración del sistema -> Sistema -> Batería -> Uso de batería por aplicación, busque la aplicación en la lista, selecciónela y establézcala en "Siempre permitido en segundo plano". Después de esto, la tarea en segundo plano siempre debe desencadenarse dentro de aproximadamente un segundo de la notificación que se recibe.