Compartilhar via


Ouvinte de notificação: acessar todas as notificações

O ouvinte de notificação fornece acesso às notificações de um usuário. Smartwatches e outros wearables podem usar o ouvinte de notificação para enviar as notificações do telefone para o dispositivo wearable. Os aplicativos de automação residencial podem usar o ouvinte de notificação para executar ações específicas quando as notificações são recebidas, como fazer as luzes piscarem quando você recebe uma chamada.

Importante

Requer Atualização de Aniversário: você deve direcionar o SDK 14393 e estar executando o build 14393 ou posterior para usar o Ouvinte de Notificação.

APIs importantes: classe UserNotificationListener, classe UserNotificationChangedTrigger

Habilite o ouvinte adicionando o recurso de Notificação do Usuário

Para usar o ouvinte de notificação, você deve adicionar o recurso Ouvinte de Notificação do Usuário ao manifesto do aplicativo.

  1. No Visual Studio, no Gerenciador de Soluções, clique duas vezes no Package.appxmanifest arquivo para abrir o designer de manifesto.
  2. Abra a guia Capacidades.
  3. Verifique o recurso do Ouvinte de Notificação do Usuário.

Verifique se o ouvinte é compatível

Se o aplicativo der suporte a versões mais antigas do Windows 10, você precisará usar a classe ApiInformation para verificar se há suporte para o ouvinte. Se não houver suporte para o ouvinte, evite executar chamadas para as APIs do ouvinte.

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

Solicitando acesso ao listener

Como o ouvinte permite o acesso às notificações do usuário, os usuários devem dar permissão ao seu aplicativo para acessar suas notificações. Durante a experiência de primeira execução do aplicativo, você deve solicitar acesso para usar o ouvinte de notificação. Se desejar, você pode mostrar alguma interface do usuário preliminar que explique por que seu aplicativo precisa de acesso às notificações do usuário antes de chamar RequestAccessAsync, para que o usuário entenda por que ele deve permitir o acesso.

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

O usuário pode revogar o acesso a qualquer momento por meio das Configurações do Windows. Portanto, seu aplicativo deve sempre verificar o status de acesso por meio do método GetAccessStatus antes de executar o código que usa o ouvinte de notificação. Se o usuário revogar o acesso, as APIs falharão silenciosamente em vez de lançar uma exceção (por exemplo, a API para obter todas as notificações simplesmente retornará uma lista vazia).

Acessar as notificações do usuário

Com o ouvinte de notificação, você pode obter uma lista das notificações atuais do usuário. Basta chamar o método GetNotificationsAsync e especificar o tipo de notificações que você deseja obter (atualmente, o único tipo de notificação com suporte são notificações do sistema).

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

Exibindo as notificações

Cada notificação é representada como um UserNotification, que fornece informações sobre o aplicativo do qual a notificação é, a hora em que a notificação foi criada, a ID da notificação e a própria notificação.

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

A propriedade AppInfo fornece as informações necessárias para exibir a notificação.

Observação

Recomendamos envolver todo o seu código para processar uma única notificação em um try/catch, caso ocorra uma exceção inesperada quando você estiver capturando uma única notificação. Você não deve deixar completamente de exibir outras notificações apenas por causa de um problema com uma notificação 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());

O conteúdo da notificação em si, como o texto da notificação, está contido na propriedade Notification . Essa propriedade contém a parte visual da notificação. (Se você estiver familiarizado com o envio de notificações no Windows, notará que o As propriedades Visual e Visual.Bindings no objeto Notification correspondem ao que os desenvolvedores enviam ao exibir uma notificação.)

Queremos procurar a associação do sistema (para código à prova de erros, você deve verificar se a associação não é nula). A partir da associação, você pode obter os elementos de texto. Você pode optar por exibir quantos elementos de texto desejar. (Idealmente, você deve exibir todos eles.) Você pode optar por tratar os elementos de texto de forma diferente; Por exemplo, trate o primeiro como texto do título e os elementos subsequentes como corpo do texto.

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

Remover uma notificação específica

Se o wearable ou serviço permitir que o usuário ignore notificações, você poderá remover a notificação real para que o usuário não a veja mais tarde no smartphone ou no computador. Basta fornecer a ID de notificação (obtida do objeto UserNotification ) da notificação que você deseja remover:

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

Limpar todas as notificações

O método UserNotificationListener.ClearNotifications limpa todas as notificações do usuário. Use esse método com cuidado. Você só deve limpar todas as notificações se o wearable ou serviço exibir TODAS as notificações. Se o wearable ou serviço exibir apenas determinadas notificações, quando o usuário clicar no botão "Limpar notificações", o usuário espera apenas que essas notificações específicas sejam removidas; no entanto, chamar o método ClearNotifications faria com que todas as notificações, incluindo aquelas que seu wearable ou serviço não estava exibindo, fossem removidas.

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

Tarefa em segundo plano para notificação adicionada/descartada

Uma maneira comum de permitir que um aplicativo ouça notificações é configurar uma tarefa em segundo plano, para que você possa saber quando uma notificação foi adicionada ou descartada, independentemente de seu aplicativo estar em execução no momento.

Graças ao modelo de processo único adicionado na Atualização de Aniversário, adicionar tarefas em segundo plano é bastante simples. No código do aplicativo principal, depois de obter o acesso do usuário ao Ouvinte de Notificação e obter acesso para executar tarefas em segundo plano chamando UserNotificationListener.Current.RequestAccessAsync e BackgroundExecutionManager.RequestAccessAsync , respectivamente, basta registrar uma nova tarefa em segundo plano e definir o UserNotificationChangedTrigger usando o tipo de notificação do 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();
}

Em seguida, em seu App.xaml.cs, substitua o método OnBackgroundActivated se ainda não tiver feito isso e use uma instrução switch no nome da tarefa para determinar qual dos muitos gatilhos de tarefa em segundo plano foi invocado.

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

A tarefa em segundo plano é simplesmente um "toque no ombro": ela não fornece nenhuma informação sobre qual notificação específica foi adicionada ou removida. Quando sua tarefa em segundo plano é acionada, você deve sincronizar as notificações em seu wearable para que elas reflitam as notificações na plataforma. Isso garante que, se a tarefa em segundo plano falhar, as notificações no wearable ainda possam ser recuperadas na próxima vez que a tarefa em segundo plano for executada.

SyncNotifications é um método que você implementa; A próxima seção mostra como.

Determinando quais notificações foram adicionadas e removidas

Em seu SyncNotifications método, para determinar quais notificações foram adicionadas ou removidas (sincronizando notificações com seu wearable), você precisa calcular o delta entre sua coleção de notificações atual e as notificações na 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 em primeiro plano para notificação adicionada/ignorada

Importante

Problema conhecido: em builds anteriores ao Build 17763 / Atualização de outubro de 2018 / versão 1809, o evento em primeiro plano causará um loop de CPU e/ou não funcionou. Se você precisar de suporte nessas compilações anteriores, use a tarefa em segundo plano.

Você também pode ouvir notificações de um manipulador de eventos na memória...

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

Como corrigir atrasos na tarefa em segundo plano

Ao testar seu aplicativo, você pode notar que a tarefa em segundo plano às vezes é atrasada e não é disparada por vários minutos. Para corrigir o atraso, solicite que o usuário acesse as configurações do sistema -> Sistema -> Bateria -> Uso da bateria por aplicativo, encontre seu aplicativo na lista, selecione-o e defina-o como "Sempre permitido em segundo plano". Depois disso, a tarefa em segundo plano sempre deve ser acionada em cerca de um segundo após o recebimento da notificação.