Visão geral dos Serviços de Notificação por Push do Windows (WNS)

O Serviço de Notificação por Push do Windows (WNS) permite que desenvolvedores de terceiros enviem atualizações de notificações do sistema, de blocos, de selos e brutas de seu próprio serviço de nuvem. Isso proporciona um mecanismo para entregar novas atualizações aos usuários de forma eficaz e confiável.

Como ele funciona

O diagrama a seguir mostra o fluxo de dados completo para enviar uma notificação por push. Ele envolve estas etapas:

  1. Seu aplicativo solicita um canal de notificação por push do WNS.
  2. O Windows pede ao WNS para criar um canal de notificação. Esse canal é retornado ao dispositivo de chamada na forma de um URI (Uniform Resource Identifier).
  3. O URI do canal de notificação é retornado pelo WNS para seu aplicativo.
  4. Seu aplicativo envia o URI para seu próprio serviço de nuvem. Em seguida, você armazena o URI em seu próprio serviço de nuvem para que possa acessar o URI ao enviar notificações. O URI é uma interface entre seu próprio aplicativo e seu próprio serviço; é sua responsabilidade implementar essa interface com padrões da Web seguros.
  5. Quando o serviço de nuvem tem uma atualização para enviar, ele notifica o WNS usando o URI do canal. Isso é feito emitindo uma solicitação POST HTTP, incluindo o conteúdo de notificação, por meio do protocolo SSL. Esta etapa requer autenticação.
  6. O WNS recebe a solicitação e roteia a notificação para o dispositivo apropriado.

wns data flow diagram for push notification

Registrar seu aplicativo e receber as credenciais para o seu serviço de nuvem

Antes de enviar notificações usando o WNS, seu aplicativo deve ser registrado no Painel da Loja, conforme descrito aqui.

Solicitar um canal de notificação

Quando um aplicativo capaz de receber notificações por push é executado, ele deve primeiro solicitar um canal de notificação por meio do CreatePushNotificationChannelForApplicationAsync. Para obter uma discussão completa e um código de exemplo, confira Como solicitar, criar e salvar um canal de notificação. Essa API retorna um URI de canal que está vinculado exclusivamente ao aplicativo de chamada e seu bloco e por meio do qual todos os tipos de notificação podem ser enviados.

Depois que o aplicativo tiver criado um URI de canal com êxito, ele o enviará para seu serviço de nuvem, juntamente com todos os metadados específicos do aplicativo que devem ser associados a esse URI.

Observações importantes

  • Não garantimos que o URI do canal de notificação para um aplicativo sempre permanecerá o mesmo. Aconselhamos que o aplicativo solicite um novo canal sempre que ele é executado e atualiza seu serviço quando o URI é alterado. O desenvolvedor nunca deve modificar o URI do canal e deve considerá-lo como uma cadeia de caracteres de caixa preta. Neste momento, as URIs do canal expiram após 30 dias. Se o aplicativo do Windows 10 renovar periodicamente seu canal em segundo plano, você poderá baixar o Exemplo de notificações por push e periódicas para o Windows 8.1 e reutilizar o seu código-fonte e/ou o padrão que ele demonstra.
  • A interface entre o serviço de nuvem e o aplicativo cliente é implementada por você, o desenvolvedor. Recomendamos que o aplicativo passe por um processo de autenticação com seu próprio serviço e transmita dados por meio de um protocolo seguro, como HTTPS.
  • É importante que o serviço de nuvem sempre garanta que o URI do canal use o domínio "notify.windows.com". O serviço nunca deve enviar notificações por push para um canal em qualquer outro domínio. Se o retorno de chamada do aplicativo for comprometido, um invasor mal-intencionado poderá enviar um URI de canal para falsificar o WNS. Sem inspecionar o domínio, seu serviço de nuvem poderia potencialmente divulgar informações para esse invasor sem saber. O subdomínio do URI do canal está sujeito a alterações e não deve ser considerado ao validar o URI do canal.
  • Se o serviço de nuvem tentar entregar uma notificação a um canal expirado, o WNS retornará o código de resposta 410. Em resposta a esse código, seu serviço não deve mais tentar enviar notificações para esse URI.

Autenticar o seu serviço de nuvem

Para enviar uma notificação, o serviço de nuvem deve ser autenticado por meio do WNS. A primeira etapa desse processo ocorre quando você registra seu aplicativo no Painel da Microsoft Store. Durante o processo de registro, seu aplicativo recebe um identificador de segurança (SID) do pacote e uma chave secreta. Essas informações são usadas pelo serviço de nuvem para autenticar com o WNS.

O esquema de autenticação do WNS é implementado usando o perfil de credenciais do cliente do protocolo OAuth 2.0. O serviço de nuvem é autenticado com o WNS fornecendo suas credenciais (SID do pacote e chave secreta). Em troca, ele recebe um token de acesso. Esse token de acesso permite que um serviço de nuvem envie uma notificação. O token é necessário a cada solicitação de notificação enviada ao WNS.

Em um alto nível, a cadeia de informações é a seguinte:

  1. O serviço de nuvem envia suas credenciais para o WNS via HTTPS seguindo o protocolo OAuth 2.0. Isso autentica o serviço com o WNS.
  2. O WNS retornará um token de acesso se a autenticação tiver sido bem-sucedida. Esse token de acesso é usado em todas as solicitações de notificação subsequentes até expirar.

wns diagram for cloud service authentication

Na autenticação com o WNS, o serviço de nuvem envia uma solicitação HTTP por meio do protocolo SSL. Os parâmetros são fornecidos no formato "application/x-www-for-urlencoded". Forneça o SID do Pacote no campo "client_id" e sua chave secreta no campo "client_secret", conforme mostrado no exemplo a seguir. Para obter detalhes de sintaxe, confira a referência de solicitação de token de acesso.

Observação

Este é apenas um exemplo, não código copia-e-cola que você pode usar com êxito em seu próprio código. 

 POST /accesstoken.srf HTTP/1.1
 Content-Type: application/x-www-form-urlencoded
 Host: https://login.live.com
 Content-Length: 211
 
 grant_type=client_credentials&client_id=ms-app%3a%2f%2fS-1-15-2-2972962901-2322836549-3722629029-1345238579-3987825745-2155616079-650196962&client_secret=Vex8L9WOFZuj95euaLrvSH7XyoDhLJc7&scope=notify.windows.com

O WNS autentica o serviço de nuvem e, se bem-sucedido, envia uma resposta de "200 OK". O token de acesso é retornado nos parâmetros incluídos no corpo da resposta HTTP, usando o tipo de mídia "application/json". Depois que o serviço receber o token de acesso, você estará pronto para enviar notificações.

O exemplo a seguir mostra uma resposta de autenticação bem-sucedida, incluindo o token de acesso. Para obter detalhes de sintaxe, confira Cabeçalhos de solicitação e resposta do serviço de notificação por push.

 HTTP/1.1 200 OK   
 Cache-Control: no-store
 Content-Length: 422
 Content-Type: application/json
 
 {
     "access_token":"EgAcAQMAAAAALYAAY/c+Huwi3Fv4Ck10UrKNmtxRO6Njk2MgA=", 
     "token_type":"bearer"
 }

Observações importantes

  • O protocolo OAuth 2.0 com suporte neste procedimento segue a versão de rascunho V16.
  • O Request For Comments (RFC) do OAuth usa o termo "cliente" para se referir ao serviço de nuvem.
  • Poderá haver alterações nesse procedimento quando o rascunho do OAuth for finalizado.
  • O token de acesso pode ser reutilizado para várias solicitações de notificação. Isso permite que o serviço de nuvem se autentique apenas uma vez para enviar várias notificações. No entanto, quando o token de acesso expira, o serviço de nuvem deve se autenticar novamente para receber um novo token de acesso.

Enviar uma notificação

Usando o URI do canal, o serviço de nuvem pode enviar uma notificação sempre que ele tiver uma atualização para o usuário.

O token de acesso descrito acima pode ser reutilizado para várias solicitações de notificação; o servidor de nuvem não é necessário para solicitar um novo token de acesso para cada notificação. Se o token de acesso tiver expirado, a solicitação de notificação retornará um erro. Recomendamos que você não tente enviar novamente sua notificação mais de uma vez se o token de acesso for rejeitado. Se você encontrar esse erro, precisará solicitar um novo token de acesso e reenviar a notificação. Para obter o código de erro exato, confira Códigos de resposta de notificação por push.

  1. O serviço de nuvem faz uma solicitação POST HTTP para o URI do canal. Essa solicitação deve ser feita por SSL e contém os cabeçalhos necessários e o conteúdo da notificação. O cabeçalho de autorização deve incluir o token de acesso adquirido para autorização.

    Uma solicitação de exemplo é mostrada aqui. Para obter detalhes de sintaxe, confira Códigos de resposta de notificação por push.

    Para obter detalhes sobre como redigir o conteúdo da notificação, confira Início rápido: enviar uma notificação por push. A carga de uma notificação por push de bloco, do sistema ou de selo é fornecida como conteúdo XML que adere ao respectivo Esquema de blocos adaptáveis definido ou ao Esquema de blocos herdados. O conteúdo de uma notificação bruta não tem uma estrutura especificada. Ele é estritamente definido pelo aplicativo.

     POST https://cloud.notify.windows.com/?token=AQE%bU%2fSjZOCvRjjpILow%3d%3d HTTP/1.1
     Content-Type: text/xml
     X-WNS-Type: wns/tile
     Authorization: Bearer EgAcAQMAAAAALYAAY/c+Huwi3Fv4Ck10UrKNmtxRO6Njk2MgA=
     Host: cloud.notify.windows.com
     Content-Length: 24
    
     <body>
     ....
    
  2. O WNS responde para indicar que a notificação foi recebida e será entregue na próxima oportunidade disponível. No entanto, o WNS não fornece confirmação de ponta a ponta de que sua notificação foi recebida pelo dispositivo ou aplicativo.

Este diagrama ilustra o fluxo de dados:

wns diagram for sending a notification

Observações importantes

  • O WNS não garante a confiabilidade ou a latência de uma notificação.
  • As notificações nunca devem incluir dados confidenciais, sensíveis ou pessoais.
  • Para enviar uma notificação, o serviço de nuvem deve primeiro autenticar-se com o WNS e receber um token de acesso.
  • Um token de acesso só permite que um serviço de nuvem envie notificações para o aplicativo único para o qual o token foi criado. Um token de acesso não pode ser usado para enviar notificações em vários aplicativos. Portanto, se o serviço de nuvem der suporte a vários aplicativos, ele deverá fornecer o token de acesso correto para o aplicativo ao enviar uma notificação por push para cada URI de canal.
  • Quando o dispositivo estiver offline, por padrão, o WNS armazenará uma notificação de cada tipo (bloco, selo, sistema) para cada URI de canal, e nenhuma notificação bruta.
  • Em cenários em que o conteúdo da notificação é personalizado para o usuário, o WNS recomenda que o serviço de nuvem envie imediatamente essas atualizações quando elas forem recebidas. Exemplos desse cenário incluem atualizações de feed de redes sociais, convites de comunicação instantânea, novas notificações de mensagem ou alertas. Como alternativa, você pode ter cenários em que a mesma atualização genérica é frequentemente entregue a um grande subconjunto de seus usuários; por exemplo, previsão do tempo, estoque e atualizações de notícias. As diretrizes do WNS especificam que a frequência dessas atualizações deve ser no máximo uma a cada 30 minutos. O usuário final ou o WNS pode determinar que atualizações de rotina mais frequentes são abusivas.
  • A Plataforma de Notificação do Windows mantém uma conexão de dados periódica com o WNS para manter o soquete ativo e íntegro. Se não houver aplicativos solicitando ou usando canais de notificação, o soquete não será criado.

Expiração de notificações de bloco e selo

Por padrão, as notificações de bloco e selo expiram três dias após serem baixadas. Quando uma notificação expira, o conteúdo é removido do bloco ou da fila e não é mais mostrado ao usuário. É uma prática recomendada definir uma expiração (usando um tempo que faz sentido para seu aplicativo) em todas as notificações de bloco e selo para que o conteúdo do bloco não persista por mais tempo do que é relevante. Um tempo de expiração explícito é essencial para o conteúdo com um tempo de vida definido. Isso também garante a remoção de conteúdo obsoleto se o serviço de nuvem parar de enviar notificações ou se o usuário se desconectar da rede por um longo período.

Seu serviço de nuvem pode definir uma expiração para cada notificação definindo o cabeçalho HTTP X-WNS-TTL para especificar o tempo (em segundos) em que a notificação permanecerá válida após o envio. Para obter mais informações, confira Cabeçalhos de solicitação e resposta do serviço de notificação por push.

Por exemplo, durante um dia de negociação ativo de um mercado de ações, você pode definir a expiração de uma atualização do preço das ações como o dobro do intervalo de envio (como uma hora após o recebimento, se você estiver enviando notificações a cada meia hora). Como outro exemplo, um aplicativo de notícias pode determinar que um dia é um prazo de expiração apropriado para uma atualização de bloco de notícias diárias.

Notificações por push e economia de bateria

A economia de bateria estende a duração da bateria limitando a atividade em segundo plano no dispositivo. O Windows 10 permite que o usuário defina que a economia de bateria seja ativada automaticamente quando a bateria ficar abaixo de um limite especificado. Quando a economia de bateria está ativada, o recebimento de notificações por push é desabilitado para economizar energia. Mas há algumas exceções a isso. As seguintes configurações de economia de bateria do Windows 10 (encontradas no aplicativo Configurações) permitem que seu aplicativo receba notificações por push mesmo quando a economia de bateria estiver ativada.

  • Permitir notificações por push de qualquer aplicativo durante a economia de bateria: essa configuração permite que todos os aplicativos recebam notificações por push enquanto a economia de bateria está ativada. Observe que essa configuração se aplica somente a edições do Windows 10 para área de trabalho (Home, Pro, Enterprise e Education).
  • Sempre permitido: essa configuração permite que aplicativos específicos sejam executados em segundo plano enquanto a economia de bateria está ativada, incluindo o recebimento de notificações por push. Essa lista é mantida manualmente pelo usuário.

Não há como verificar o estado dessas duas configurações, mas você pode verificar o estado da economia de bateria. No Windows 10, use a propriedade EnergySaverStatus para verificar o estado de economia de bateria. Seu aplicativo também pode usar o evento EnergySaverStatusChanged para escutar alterações na economia de bateria.

Se o aplicativo depender muito das notificações por push, recomendamos notificar os usuários de que eles podem não receber notificações enquanto a economia de bateria estiver ativada, e tornar mais fácil para eles ajustarem as configurações de economia de bateria. Usando o esquema de URI de configurações de economia de bateria no Windows 10, ms-settings:batterysaver-settings, você pode fornecer um link conveniente para o aplicativo Configurações.

Dica

Ao notificar o usuário sobre as configurações de economia de bateria, recomendamos fornecer uma maneira de suprimir a mensagem no futuro. Por exemplo, a caixa de seleção dontAskMeAgainBox no exemplo a seguir persiste a preferência do usuário em LocalSettings.

Aqui está um exemplo de como verificar se a economia de bateria está ativada no Windows 10. Este exemplo notifica o usuário e inicia o aplicativo Configurações para as configurações de economia de bateria. O dontAskAgainSetting permite ao usuário suprimir a mensagem se ele não quiser ser notificado novamente.

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.System;
using Windows.System.Power;
...
...
async public void CheckForEnergySaving()
{
   //Get reminder preference from LocalSettings
   bool dontAskAgain;
   var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
   object dontAskSetting = localSettings.Values["dontAskAgainSetting"];
   if (dontAskSetting == null)
   {  // Setting does not exist
      dontAskAgain = false;
   }
   else
   {  // Retrieve setting value
      dontAskAgain = Convert.ToBoolean(dontAskSetting);
   }
   
   // Check if battery saver is on and that it's okay to raise dialog
   if ((PowerManager.EnergySaverStatus == EnergySaverStatus.On)
         && (dontAskAgain == false))
   {
      // Check dialog results
      ContentDialogResult dialogResult = await saveEnergyDialog.ShowAsync();
      if (dialogResult == ContentDialogResult.Primary)
      {
         // Launch battery saver settings (settings are available only when a battery is present)
         await Launcher.LaunchUriAsync(new Uri("ms-settings:batterysaver-settings"));
      }

      // Save reminder preference
      if (dontAskAgainBox.IsChecked == true)
      {  // Don't raise dialog again
         localSettings.Values["dontAskAgainSetting"] = "true";
      }
   }
}
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.System.Power.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Navigation.h>
using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::System;
using namespace winrt::Windows::System::Power;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Navigation;
...
winrt::fire_and_forget CheckForEnergySaving()
{
    // Get reminder preference from LocalSettings.
    bool dontAskAgain{ false };
    auto localSettings = ApplicationData::Current().LocalSettings();
    IInspectable dontAskSetting = localSettings.Values().Lookup(L"dontAskAgainSetting");
    if (!dontAskSetting)
    {
        // Setting doesn't exist.
        dontAskAgain = false;
    }
    else
    {
        // Retrieve setting value
        dontAskAgain = winrt::unbox_value<bool>(dontAskSetting);
    }

    // Check whether battery saver is on, and whether it's okay to raise dialog.
    if ((PowerManager::EnergySaverStatus() == EnergySaverStatus::On) && (!dontAskAgain))
    {
        // Check dialog results.
        ContentDialogResult dialogResult = co_await saveEnergyDialog().ShowAsync();
        if (dialogResult == ContentDialogResult::Primary)
        {
            // Launch battery saver settings
            // (settings are available only when a battery is present).
            co_await Launcher::LaunchUriAsync(Uri(L"ms-settings:batterysaver-settings"));
        }

        // Save reminder preference.
        if (dontAskAgainBox().IsChecked())
        {
            // Don't raise the dialog again.
            localSettings.Values().Insert(L"dontAskAgainSetting", winrt::box_value(true));
        }
    }
}

Este é o XAML para o ContentDialog apresentado neste exemplo.

<ContentDialog x:Name="saveEnergyDialog"
               PrimaryButtonText="Open battery saver settings"
               SecondaryButtonText="Ignore"
               Title="Battery saver is on."> 
   <StackPanel>
      <TextBlock TextWrapping="WrapWholeWords">
         <LineBreak/><Run>Battery saver is on and you may 
          not receive push notifications.</Run><LineBreak/>
         <LineBreak/><Run>You can choose to allow this app to work normally
         while in battery saver, including receiving push notifications.</Run>
         <LineBreak/>
      </TextBlock>
      <CheckBox x:Name="dontAskAgainBox" Content="OK, got it."/>
   </StackPanel>
</ContentDialog>