Listener di notifica: accedere a tutte le notificheNotification listener: Access all notifications

Il listener di notifica consente di accedere alle notifiche di un utente.The notification listener provides access to a user's notifications. Smartwatches e altri Wearable possono usare il listener di notifica per inviare le notifiche del telefono al dispositivo indossabile.Smartwatches and other wearables can use the notification listener to send the phone's notifications to the wearable device. Le app di automazione domestica possono usare il listener di notifiche per eseguire azioni specifiche quando vengono ricevute le notifiche, ad esempio quando si riceve una chiamata.Home automation apps can use notification listener to perform specific actions when notifications are received, such as making the lights blink when you receive a call.

Importante

Richiede l'aggiornamento dell'anniversario : è necessario destinare l'SDK 14393 ed eseguire build 14393 o versione successiva per usare il listener di notifica.Requires Anniversary Update : You must target SDK 14393 and be running build 14393 or higher to use Notification Listener.

API importanti : classe UserNotificationListener, classe UserNotificationChangedTriggerImportant APIs : UserNotificationListener class, UserNotificationChangedTrigger class

Abilitare il listener aggiungendo la funzionalità di notifica utenteEnable the listener by adding the User Notification capability

Per usare il listener di notifica, è necessario aggiungere la funzionalità listener notifiche utente al manifesto dell'applicazione.To use the notification listener, you must add the User Notification Listener capability to your app manifest.

  1. In Visual Studio, nella Esplora soluzioni fare doppio clic sul Package.appxmanifest file per aprire la finestra di progettazione del manifesto.In Visual Studio, in the Solution Explorer, double click your Package.appxmanifest file to open the manifest designer.
  2. Apri la scheda Funzionalità.Open the Capabilities tab.
  3. Controllare la funzionalità listener notifiche utente .Check the User Notification Listener capability.

Controllare se il listener è supportatoCheck whether the listener is supported

Se l'app supporta le versioni precedenti di Windows 10, è necessario usare la classe ApiInformation per verificare se il listener è supportato.If your app supports older versions of Windows 10, you need to use the ApiInformation class to check whether the listener is supported. Se il listener non è supportato, evitare di eseguire chiamate alle API del listener.If the listener isn't supported, avoid executing any calls to the listener APIs.

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

Richiesta di accesso al listenerRequesting access to the listener

Poiché il listener consente l'accesso alle notifiche dell'utente, gli utenti devono concedere all'app l'autorizzazione per accedere alle notifiche.Since the listener allows access to the user's notifications, users must give your app permission to access their notifications. Durante la prima esecuzione dell'app, è necessario richiedere l'accesso per usare il listener di notifica.During your app's first-run experience, you should request access to use the notification listener. Se lo si desidera, è possibile visualizzare un'interfaccia utente preliminare che spiega perché l'app deve accedere alle notifiche dell'utente prima di chiamare RequestAccessAsync, in modo che l'utente possa comprendere il motivo per cui deve consentire l'accesso.If you want, you can show some preliminary UI that explains why your app needs access to the user's notifications before you call RequestAccessAsync, so that the user understands why they should allow access.

// 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;
}

L'utente può revocare l'accesso in qualsiasi momento tramite le impostazioni di Windows.The user can revoke access at any time via Windows Settings. Quindi, l'app deve sempre controllare lo stato di accesso tramite il metodo GetAccessStatus prima di eseguire codice che usa il listener di notifica.Therefore, your app should always check the access status via the GetAccessStatus method before executing code that uses the notification listener. Se l'utente revoca l'accesso, le API avranno automaticamente esito negativo anziché generare un'eccezione (ad esempio, l'API per ottenere tutte le notifiche restituirà semplicemente un elenco vuoto).If the user revokes access, the APIs will silently fail rather than throwing an exception (for example, the API to get all notifications will simply return an empty list).

Accedere alle notifiche dell'utenteAccess the user's notifications

Con il listener di notifica, è possibile ottenere un elenco delle notifiche correnti dell'utente.With the notification listener, you can get a list of the user's current notifications. È sufficiente chiamare il metodo GetNotificationsAsync e specificare il tipo di notifiche che si desidera ottenere (attualmente, l'unico tipo di notifiche supportate sono le notifiche di tipo avviso popup).Simply call the GetNotificationsAsync method, and specify the type of notifications you want to get (currently, the only type of notifications supported are toast notifications).

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

Visualizzazione delle notificheDisplaying the notifications

Ogni notifica viene rappresentata come UserNotification, che fornisce informazioni sull'app da cui viene notificata la notifica, l'ora di creazione della notifica, l'ID della notifica e la notifica stessa.Each notification is represented as a UserNotification, which provides information about the app that the notification is from, the time the notification was created, the notification's ID, and the notification itself.

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

La proprietà appinfo fornisce le informazioni necessarie per visualizzare la notifica.The AppInfo property provides the info you need to display the notification.

Nota

È consigliabile racchiudere tutto il codice per l'elaborazione di una singola notifica in un'operazione try/catch, nel caso in cui si verifichi un'eccezione imprevista quando si acquisisce una singola notifica.We recommend surrounding all your code for processing a single notification in a try/catch, in case an unexpected exception occurs when you are capturing a single notification. Non è necessario visualizzare completamente altre notifiche solo a causa di un problema con una notifica specifica.You shouldn't completely fail to display other notifications just because of an issue with one specific notification.

// 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());

Il contenuto della notifica stessa, ad esempio il testo della notifica, è contenuto nella proprietà di notifica .The content of the notification itself, such as the notification text, is contained in the Notification property. Questa proprietà contiene la parte visiva della notifica.This property contains the visual portion of the notification. Se si ha familiarità con l'invio di notifiche in Windows, si noterà che le proprietà Visual e Visual. Bindings nell'oggetto Notification corrispondono a ciò che gli sviluppatori inviano quando viene visualizzata una notifica.(If you are familiar with sending notifications on Windows, you will notice that the Visual and Visual.Bindings properties in the Notification object correspond to what developers send when popping a notification.)

Si vuole cercare il binding di tipo avviso popup (per il codice di prova di errore, è necessario verificare che l'associazione non sia null).We want to look for the toast binding (for error-proof code, you should check that the binding isn't null). Dall'associazione è possibile ottenere gli elementi di testo.From the binding, you can obtain the text elements. È possibile scegliere di visualizzare tutti gli elementi di testo desiderati.You can choose to display as many text elements as you would like. Idealmente, è consigliabile visualizzarli tutti. È possibile scegliere di trattare gli elementi di testo in modo diverso; ad esempio, considerare il primo come testo del titolo e gli elementi successivi come testo del corpo.(Ideally, you should display them all.) You can choose to treat the text elements differently; for example, treat the first one as title text, and subsequent elements as body text.

// 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));
}

Rimuovere una notifica specificaRemove a specific notification

Se il dispositivo indossabile o il servizio consente all'utente di ignorare le notifiche, è possibile rimuovere la notifica effettiva in modo che l'utente non la visualizzi in un secondo momento sul telefono o sul PC.If your wearable or service allows the user to dismiss notifications, you can remove the actual notification so the user doesn't see it later on their phone or PC. È sufficiente fornire l'ID notifica (ottenuto dall'oggetto UserNotification ) della notifica che si vuole rimuovere:Simply provide the notification ID (obtained from the UserNotification object) of the notification you'd like to remove:

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

Cancella tutte le notificheClear all notifications

Il metodo UserNotificationListener. ClearNotifications Cancella tutte le notifiche dell'utente.The UserNotificationListener.ClearNotifications method clears all the user's notifications. Utilizzare questo metodo con cautela.Use this method with caution. È consigliabile cancellare tutte le notifiche solo se il servizio indossabile o il servizio Visualizza tutte le notifiche.You should only clear all notifications if your wearable or service displays ALL notifications. Se il dispositivo indossabile o il servizio Visualizza solo determinate notifiche, quando l'utente fa clic sul pulsante "Cancella notifiche", l'utente si aspetta solo che vengano rimosse le notifiche specifiche. Tuttavia, la chiamata al metodo ClearNotifications provocherebbe effettivamente la rimozione di tutte le notifiche, incluse quelle non visualizzate dal dispositivo indossabile o dal servizio.If your wearable or service only displays certain notifications, when the user clicks your "Clear notifications" button, the user is only expecting those specific notifications to be removed; however, calling the ClearNotifications method would actually cause all the notifications, including ones that your wearable or service wasn't displaying, to be removed.

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

Attività in background per la notifica aggiunta/rilasciataBackground task for notification added/dismissed

Un modo comune per consentire a un'app di restare in ascolto delle notifiche consiste nell'impostare un'attività in background, in modo da poter sapere quando una notifica è stata aggiunta o ignorata, indipendentemente dal fatto che l'app sia attualmente in esecuzione.A common way to enable an app to listen to notifications is to set up a background task, so that you can know when a notification was added or dismissed regardless of whether your app is currently running.

Grazie al modello a processo singolo aggiunto nell'aggiornamento dell'anniversario, l'aggiunta di attività in background è piuttosto semplice.Thanks to the single process model added in the Anniversary Update, adding background tasks is fairly simple. Nel codice dell'app principale, dopo aver ottenuto l'accesso dell'utente al listener delle notifiche e aver ottenuto l'accesso per eseguire le attività in background, è sufficiente registrare una nuova attività in background e impostare UserNotificationChangedTrigger usando il tipo di notifica di tipo avviso popup.In your main app's code, after you have obtained the user's access to Notification Listener and obtained access to run background tasks, simply register a new background task, and set the UserNotificationChangedTrigger using the Toast notification kind.

// 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();
}

Quindi, in App.xaml.cs, eseguire l'override del metodo OnBackgroundActivated , se non è ancora stato fatto, e usare un'istruzione switch sul nome dell'attività per determinare quale dei molti trigger di attività in background è stato richiamato.Then, in your App.xaml.cs, override the OnBackgroundActivated method if you haven't yet, and use a switch statement on the task name to determine which of your many background task triggers was invoked.

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();
}

L'attività in background è semplicemente un "tocco a spalla": non fornisce alcuna informazione su quale notifica specifica è stata aggiunta o rimossa.The background task is simply a "shoulder tap": it doesn't provide any information about which specific notification was added or removed. Quando viene attivata l'attività in background, è necessario sincronizzare le notifiche sul dispositivo indossabile in modo che riflettano le notifiche nella piattaforma.When your background task is triggered, you should sync the notifications on your wearable so that they reflect the notifications in the platform. In questo modo, se l'attività in background ha esito negativo, le notifiche sul dispositivo indossabile possono comunque essere recuperate la volta successiva che viene eseguita l'attività in background.This ensures that if your background task fails, notifications on your wearable can still be recovered the next time your background task executes.

SyncNotifications è un metodo implementato; nella sezione successiva viene illustrato come.SyncNotifications is a method you implement; the next section shows how.

Determinazione delle notifiche aggiunte e rimosseDetermining which notifications were added and removed

Nel SyncNotifications metodo, per determinare quali notifiche sono state aggiunte o rimosse (sincronizzazione delle notifiche con il dispositivo indossabile), è necessario calcolare il delta tra la raccolta di notifiche corrente e le notifiche nella piattaforma.In your SyncNotifications method, to determine which notifications have been added or removed (syncing notifications with your wearable), you have to calculate the delta between your current notification collection, and the notifications in the platform.

// 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 in primo piano per la notifica aggiunta/non rilasciataForeground event for notification added/dismissed

Importante

Problema noto: nelle compilazioni prima della compilazione 17763/ottobre 2018 aggiornamento/versione 1809, l'evento in primo piano provocherà un ciclo della CPU e/o non funzionerà.Known issue: In builds before Build 17763 / October 2018 Update / Version 1809, The foreground event will cause a CPU loop and/or didn't work. Se è necessario il supporto per le compilazioni precedenti, usare invece l'attività in background.If you need support on those earlier builds, use the background task instead.

È anche possibile ascoltare le notifiche da un gestore eventi in memoria...You can also listen to notifications from an in-memory event handler...

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

Come correggere i ritardi nell'attività in backgroundHow to fix delays in the background task

Quando si esegue il test dell'applicazione, è possibile notare che l'attività in background è a volte ritardata e non viene attivata per diversi minuti.When testing your app, you might notice that the background task is sometimes delayed and doesn't trigger for several minutes. Per correggere il ritardo, richiedere all'utente di passare a impostazioni di sistema-> uso della batteria > batteria > per app, trovare l'app nell'elenco, selezionarla e impostarla su "sempre consentito in background".To fix the delay, prompt the user to go to the system settings -> System -> Battery -> Battery usage by app, find your app in the list, select it, and set it to be "Always allowed in background." Successivamente, l'attività in background dovrebbe essere sempre attivata entro circa un secondo della notifica ricevuta.After this, the background task should always be triggered within around a second of the notification being received.