Partilhar via


Início Rápido: Notificações push no SDK de Aplicações Windows

Neste quickstart, irá criar uma aplicação de Windows ambiente de trabalho que envia e recebe notificações push usando o SDK de Aplicações Windows.

Prerequisites

Requisitos de embalagem

As notificações push no SDK de Aplicações Windows suportam tanto aplicações de ambiente de trabalho empacotadas como verdadeiramente não empacotadas. No entanto, a identidade do pacote é necessária para a entrega em segundo plano e ativação COM — o cenário de produção mais comum. A tabela seguinte resume o que é necessário com base no modelo da sua embalagem:

Modelo de embalagem Ativador COM necessário Mapeamento de PFN necessário Suporte para produtos não empacotados
MSIX empacotado (WinUI 3, empacotado WPF/WinForms) Sim — em Package.appxmanifest Sim — via email de mapeamento PFN No
Embalado com referência externa Sim — em Package.appxmanifest Sim — via email de mapeamento PFN No
Verdadeiramente sem embalagem (sem identidade de embalagem) Não (saltar Passo 3) No Sim — funcionalidade limitada

Important

Se a sua aplicação estiver empacotada (MSIX ou com localização externa), deve mapear o Nome da Família do Pacote (PFN) da sua aplicação ao seu Azure AppId antes de as notificações push funcionarem. Os pedidos de mapeamento são submetidos por email para Win_App_SDK_Push@microsoft.com e processados semanalmente. Planeie este período de antecedência antes do seu lançamento.

Consulte Passo 4: Mapeie o Nome da Família do Pacote da sua aplicação para o Azure AppId para mais detalhes.

Aplicativo de exemplo

Este quickstart explica como adicionar suporte a notificações push à sua aplicação no SDK de Aplicações Windows 1.7. Veja código semelhante a este quickstart nas aplicações de exemplo encontradas em GitHub. Certifica-te de verificar o branch com a tua versão preferida do SDK de Aplicações Windows para os exemplos que melhor se adequam ao teu projeto.

Também pode encontrar exemplos para cada versão do SDK de Aplicações Windows ao selecionar uma ramificação de versão no repositório de amostras.

Referência da API

Para documentação de referência da API para notificações push, consulte Microsoft.Windows.Espaço de nomes PushNotifications.

Configure a identidade da sua aplicação no Azure Active Directory (AAD)

As notificações push no SDK de Aplicações Windows usam identidades do Azure Active Directory (AAD). As credenciais Azure são necessárias ao solicitar um URI do Canal WNS e ao solicitar tokens de acesso para enviar notificações push. Nota: Não damos suporte ao uso de notificações push do SDK de Aplicações Windows com o Centro de Parceiros Microsoft.

Etapa 1: Criar um registro de aplicativo AAD

Inicie sessão na sua conta de Azure e crie um novo recurso de Registo da App AAD. Selecione Novo registo.

Etapa 2: Forneça um nome e selecione uma opção multilocatário

  1. Forneça um nome de aplicativo.

  2. As notificações por push exigem a opção multilocatário, portanto, selecione-a.

    1. Para obter mais informações sobre locatários, consulte Quem pode entrar no seu aplicativo?.
  3. Selecione Registo

  4. Toma nota do teu ID Application (cliente), pois este é o teu Azure AppId que vais usar durante o registo de ativação e o pedido do token de acesso.

  5. Tome nota do seu ID de Diretório (Tenant) , pois este é o seu Azure TenantId que utilizará ao solicitar um token de acesso.

    Important

    Registro de aplicativo AAD no locatário Anote o seu ID de Aplicação (cliente) e ID de Diretório (locatário) .

  6. Toma nota do teu ID de Objecto, pois este é o teu Azure ObjectId que vais usar ao fazer um pedido de canal. Observe que esse NÃO é o ID do objeto listado na página do Essentials. Em vez disso, para encontrar o ID de Objeto correto, clique no nome da aplicação no campo Aplicação gerida no diretório local na página Essentials:

    Captura de tela mostrando a opção Aplicativo gerenciado no diretório local na página Essentials

    Captura de tela mostrando o campo ID do objeto

    Note

    É necessário um principal de serviço para obter um ID de Objeto; se não houver um associado à sua aplicação, siga os passos de um dos seguintes artigos para criar um no portal Azure ou usando a linha de comandos:

    Use o portal para criar uma aplicação e principal de serviço AD Azure que possa aceder a recursos

    Use Azure PowerShell para criar um principal de serviço com um certificado

Etapa 3: criar um segredo para o registro do seu aplicativo

O seu segredo será usado juntamente com o seu Azure AppId/ClientId ao solicitar um token de acesso para enviar notificações push.

Segredo da App AAD

Navegue até Certificados & segredos e selecione Novo segredo do cliente.

Important

Certifique-se de copiar o seu segredo depois de criado e guardá-lo num local seguro, como o Azure Key Vault. Só será visível uma vez logo após a criação.

Passo 4: Mapeie o Nome da Família do Pacote da sua aplicação para o ID da aplicação do Azure

Se a sua aplicação estiver empacotada (incluindo uma localização externa), pode usar este fluxo para mapear o Nome da Família de Pacotes (PFN) da sua aplicação e o seu AppId do Azure.

Se a sua aplicação for uma aplicação Win32 empacotada, crie uma solicitação de mapeamento de Nome de Família de Pacote (PFN) através de email para Win_App_SDK_Push@microsoft.com com o assunto "SDK de Aplicações Windows Push Notifications Mapping Request" e no corpo "PFN: [your PFN]", "AppId: [your APPId]", "ObjectId: [your ObjectId]". As solicitações de mapeamento são concluídas semanalmente. Você será notificado assim que sua solicitação de mapeamento for concluída.

Depois de ter o seu AppId, ObjectId e segredo do Azure, pode adicionar essas credenciais ao código de exemplo abaixo.

Configurar seu aplicativo para receber notificações por push

Passo 1: Adicionar o SDK de Aplicações Windows e os pacotes NuGet necessários

De seguida, clique com o botão direito na solução no Explorador de Soluções e selecione Gerir Pacotes NuGet.

No Gestor de Pacotes, adicione os seguintes pacotes:

  • Microsoft. WindowsAppSDK (versão mínima 1.1.0)
  • Microsoft. Windows. SDK. BuildTools (versão mínima 10.0.22000.194)
  • Microsoft. Windows. CppWinRT, (versão mínima 2.0.210930.14)
  • Microsoft. Windows. ImplementationLibrary, (versão mínima 1.0.210930.1)

Se esta for a primeira vez que utiliza o SDK de Aplicações Windows no seu projeto e este está empacotado com localização externa ou desempacotado, inicialize o SDK de Aplicações Windows adicionando a seguinte propriedade ao seu ficheiro de projeto:

<!-- your .vcxproj or .proj file -->
<PropertyGroup Label="Globals">
    <!-- Other properties -->
    <WindowsPackageType>None</WindowsPackageType>
</PropertyGroup>

ou utilize a API de bootstrapper. Consulte Utilizar o runtime do SDK de Aplicações Windows para aplicações embaladas com localização externa ou não embaladas para mais detalhes.

Note

Se o SDK não for inicializado, o aplicativo será lançado System.Runtime.InteropServices.COMException (0x80040154): Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)) e não será executado.

Etapa 2: Adicionar namespaces

De seguida, adiciona o namespace para notificações push SDK de Aplicações Windows Microsoft.Windows.PushNotifications.

#include <winrt/Microsoft.Windows.PushNotifications.h>

using namespace winrt::Microsoft::Windows::PushNotifications;

Se receber um "Não consigo encontrar Microsoft.Windows. PushNotifications", isso provavelmente significa que os ficheiros de cabeçalho não foram gerados. Para resolver, certifique-se de ter os pacotes acima instalados, comente as instruções include e using que causam o erro e reconstrua o aplicativo para gerar os arquivos de cabeçalho. Quando a compilação for bem-sucedida, descomente as instruções `include` e `using` e volte a compilar o projeto. Isso deve resolver o erro.

Etapa 3: adicionar o ativador COM ao manifesto do aplicativo

Important

Se o seu aplicativo estiver desempacotado (ou seja, ele não tiver identidade de pacote no tempo de execução), pule para a Etapa 4: Registre-se e responda às notificações por push na inicialização do aplicativo.

Se o seu aplicativo estiver empacotado (inclusive empacotado com local externo): abra seu Package.appxmanifest. Adicione o seguinte dentro do elemento <Application>. Substitua os valores Id, Executablee DisplayName por valores específicos do seu aplicativo.

<!--Packaged apps only-->
<!--package.appxmanifest-->

<Package
  ...
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
  ...
  <Applications>
    <Application>
      ...
      <Extensions>

        <!--Register COM activator-->    
        <com:Extension Category="windows.comServer">
          <com:ComServer>
              <com:ExeServer Executable="SampleApp\SampleApp.exe" DisplayName="SampleApp" Arguments="----WindowsAppRuntimePushServer:">
                <com:Class Id="[Your app's Azure AppId]" DisplayName="Windows App SDK Push" />
            </com:ExeServer>
          </com:ComServer>
        </com:Extension>
    
      </Extensions>
    </Application>
  </Applications>
 </Package>    

Note

O atributo Id em <com:Class> deve ser definido para o teu Azure AppId (o ID da Aplicação (cliente) do registo da tua aplicação Azure AD). É assim que o SDK de Aplicações Windows liga a ativação COM da sua aplicação à sua identidade Azure — quando o WNS ativa a sua aplicação para enviar uma notificação push em segundo plano, usa este GUID para localizar e lançar o servidor COM correto. Use o mesmo valor do Azure AppId que referiu no Passo 1 acima.

Note

Um exemplo da classe C++ concluída para este exemplo pode ser encontrado após a Etapa 5. As etapas 4 e 5 fornecem orientação passo a passo para adicionar cada peça no exemplo final.

Etapa 4: Registre-se e responda às notificações por push na inicialização do aplicativo

Atualize o método main() do seu aplicativo para adicionar o seguinte:

  1. Registe a sua aplicação para receber notificações push chamando PushNotificationManager::Default().Register().
  2. Verifique a origem da solicitação de ativação chamando AppInstance::GetCurrent(). GetActivatedEventArgs(). Se a ativação foi acionada a partir de uma notificação push, responda com base na carga útil da notificação.

Important

Você deve chamar PushNotificationManager::Default().Registrar antes de chamar AppInstance.GetCurrent.GetActivatedEventArgs.

Adicionando manipuladores de eventos em primeiro plano

Para manipular um evento em primeiro plano, registre um manipulador para PushNotificationManager.PushReceived.

Important

Você também deve registrar qualquer manipulador de eventos PushNotificationManager.PushReceived antes de chamar PushNotificationManager.Register(). Caso contrário, a seguinte exceção de tempo de execução será lançada:

System.Runtime.InteropServices.COMException: Element not found. Must register event handlers before calling Register().

Adicione a verificação PushNotificationManager::IsSupported()

Em seguida, adicione uma verificação se as APIs PushNotification são suportadas com PushNotificationManager.IsSupported(). Caso contrário, recomendamos que você use sondagem ou sua própria implementação de soquete personalizado.

Agora que há suporte confirmado a notificações por push, adicione um comportamento baseado em PushNotificationReceivedEventArgs.

Etapa 5: Solicitar um URI do canal WNS e registrá-lo no servidor WNS

Os URIs do Canal WNS são os pontos de extremidade HTTP para o envio de notificações por push. Cada cliente deve solicitar um URI de canal e registrá-lo no servidor WNS para receber notificações push.

Note

Os URIs do canal WNS expiram após 30 dias. Peça um URI de canal novo em cada lançamento da aplicação em vez de guardar em cache um anterior. Quando o novo URI difere do que o seu backend armazenou, envie o URI atualizado para o seu serviço cloud para que ele mantenha os registos atualizados. Não assuma que o URI se manterá estável entre sessões — tratá-lo como um valor mutável, com âmbito de sessão, evita falhas de entrega silenciosa causadas por URIs de canal expirados ou obsoletos.

auto channelOperation{ PushNotificationManager::Default().CreateChannelAsync(winrt::guid("[Your app's Azure ObjectID]")) };

Se está a seguir o código do tutorial, adicione aqui o seu ID de Objeto Azure:

// To obtain an AAD RemoteIdentifier for your app,
// follow the instructions on https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app
winrt::guid remoteId{ "00000000-0000-0000-0000-000000000000" }; // Replace this with your own Azure ObjectId

O PushNotificationManager tentará criar um URI de canal, repetindo automaticamente por no máximo 15 minutos. Crie um manipulador de eventos para aguardar a conclusão da chamada. Quando a chamada for concluída, se tiver sido bem-sucedida, registre o URI no servidor WNS.

Código de exemplo

#include <iostream>
#include <winrt/Microsoft.Windows.PushNotifications.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Microsoft.Windows.AppLifecycle.h>
#include <winrt/Windows.ApplicationModel.Background.h>
#include <wil/cppwinrt.h>
#include <wil/result.h>

using namespace winrt::Microsoft::Windows::PushNotifications;
using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::Windows::AppLifecycle;

// To obtain an AAD RemoteIdentifier for your app,
// follow the instructions on https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app
winrt::guid remoteId{ "00000000-0000-0000-0000-000000000000" }; // Replace this with your own Azure ObjectId

winrt::Windows::Foundation::IAsyncOperation<PushNotificationChannel> RequestChannelAsync()
{
    auto channelOperation = PushNotificationManager::Default().CreateChannelAsync(remoteId);

    // Set up the in-progress event handler
    channelOperation.Progress(
        [](auto&& sender, auto&& args)
        {
            if (args.status == PushNotificationChannelStatus::InProgress)
            {
                // This is basically a noop since it isn't really an error state
                std::cout << "Channel request is in progress." << std::endl << std::endl;
            }
            else if (args.status == PushNotificationChannelStatus::InProgressRetry)
            {
                LOG_HR_MSG(
                    args.extendedError,
                    "The channel request is in back-off retry mode because of a retryable error! Expect delays in acquiring it. RetryCount = %d",
                    args.retryCount);
            }
        });

    auto result = co_await channelOperation;

    if (result.Status() == PushNotificationChannelStatus::CompletedSuccess)
    {
        auto channelUri = result.Channel().Uri();

        std::cout << "channelUri: " << winrt::to_string(channelUri.ToString()) << std::endl << std::endl;

        auto channelExpiry = result.Channel().ExpirationTime();

        // Caller's responsibility to keep the channel alive
        co_return result.Channel();
    }
    else if (result.Status() == PushNotificationChannelStatus::CompletedFailure)
    {
        LOG_HR_MSG(result.ExtendedError(), "We hit a critical non-retryable error with channel request!");
        co_return nullptr;
    }
    else
    {
        LOG_HR_MSG(result.ExtendedError(), "Some other failure occurred.");
        co_return nullptr;
    }

};

PushNotificationChannel RequestChannel()
{
    auto task = RequestChannelAsync();
    if (task.wait_for(std::chrono::seconds(300)) != AsyncStatus::Completed)
    {
        task.Cancel();
        return nullptr;
    }

    auto result = task.GetResults();
    return result;
}

void SubscribeForegroundEventHandler()
{
    winrt::event_token token{ PushNotificationManager::Default().PushReceived([](auto const&, PushNotificationReceivedEventArgs const& args)
    {
        auto payload{ args.Payload() };

        std::string payloadString(payload.begin(), payload.end());
        std::cout << "\nPush notification content received in the FOREGROUND: " << payloadString << std::endl;
    }) };

    std::cout << "Push notification foreground event handler registered." << std::endl;
}

int main()
{
    // Set up an event handler, so we can receive notifications in the foreground while the app is running.
    // You must register notification event handlers before calling Register(). Otherwise, the following runtime
    // exception will be thrown: System.Runtime.InteropServices.COMException: 'Element not found. Must register
    // event handlers before calling Register().'
    SubscribeForegroundEventHandler();

    // Register the app for push notifications.
    PushNotificationManager::Default().Register();

    auto args{ AppInstance::GetCurrent().GetActivatedEventArgs() };
    switch (args.Kind())
    {
        case ExtendedActivationKind::Launch:
        {
            std::cout << "App launched by user or from the debugger." << std::endl;
            if (PushNotificationManager::IsSupported())
            {
                std::cout << "Push notifications are supported on this device." << std::endl;

                // Request a WNS Channel URI which can be passed off to an external app to send notifications to.
                // The WNS Channel URI uniquely identifies this app for this user and device.
                PushNotificationChannel channel{ RequestChannel() };
                if (!channel)
                {
                    std::cout << "\nThere was an error obtaining the WNS Channel URI" << std::endl;

                    if (remoteId == winrt::guid{ "00000000-0000-0000-0000-000000000000" })
                    {
                        std::cout << "\nThe ObjectID has not been set. Refer to the readme file accompanying this sample\nfor the instructions on how to obtain and setup an ObjectID" << std::endl;
                    }
                }

                std::cout << "\nPress 'Enter' at any time to exit App." << std::endl;
                std::cin.ignore();
            }
            else
            {
                std::cout << "Push notifications are NOT supported on this device." << std::endl;
                std::cout << "App implements its own custom socket here to receive messages from the cloud since Push APIs are unsupported." << std::endl;
                std::cin.ignore();
            }
        }
        break;

        case ExtendedActivationKind::Push:
        {
            std::cout << "App activated via push notification." << std::endl;
            PushNotificationReceivedEventArgs pushArgs{ args.Data().as<PushNotificationReceivedEventArgs>() };

            // Call GetDeferral to ensure that code runs in low power
            auto deferral{ pushArgs.GetDeferral() };

            auto payload{ pushArgs.Payload() };

            // Do stuff to process the raw notification payload
            std::string payloadString(payload.begin(), payload.end());
            std::cout << "\nPush notification content received in the BACKGROUND: " << payloadString.c_str() << std::endl;
            std::cout << "\nPress 'Enter' to exit the App." << std::endl;

            // Call Complete on the deferral when finished processing the payload.
            // This removes the override that kept the app running even when the system was in a low power mode.

            deferral.Complete();
            std::cin.ignore();
        }
        break;

        default:
            std::cout << "\nUnexpected activation type" << std::endl;
            std::cout << "\nPress 'Enter' to exit the App." << std::endl;
            std::cin.ignore();
            break;
    }
}

Etapa 6: Criar e instalar seu aplicativo

Usa o Visual Studio para construir e instalar a tua aplicação. Clique com o botão direito no ficheiro da solução na Explorador de Soluções e selecione Deploy. O Visual Studio vai construir a tua aplicação e instalá-la na tua máquina. Pode correr a aplicação abrindo-a através do Menu Iniciar ou do depurador do Visual Studio.

O console do código do tutorial terá esta aparência:

Exemplo de console de trabalho

Você precisará do token para enviar uma notificação por push para seu aplicativo.

Enviar uma notificação por push para seu aplicativo

Neste ponto, toda a configuração está concluída e o servidor WNS pode enviar notificações por push para aplicativos cliente. Nas etapas a seguir, consulte os cabeçalhos de solicitação e resposta do servidor de notificação por push e para obter mais detalhes.

Etapa 1: Solicitar um token de acesso

Para enviar uma notificação por push, o servidor WNS primeiro precisa solicitar um token de acesso. Envie um pedido HTTP POST com o seu Azure Tenant ID, Azure App ID, e chave secreta. Para informações sobre como recuperar o Azure TenantId e Azure AppId, consulte Obter valores de tenant e ID de aplicação para iniciar sessão.

Solicitação de exemplo HTTP:

POST /{tenantID}/oauth2/v2.0/token Http/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 160

grant_type=client_credentials&client_id=<Azure_App_Registration_AppId_Here>&client_secret=<Azure_App_Registration_Secret_Here>&scope=https://wns.windows.com/.default/

Solicitação de amostra em C#:

//Sample C# Access token request
var client = new RestClient("https://login.microsoftonline.com/{tenantID}/oauth2/v2.0");
var request = new RestRequest("/token", Method.Post);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("client_id", "[Your app's Azure AppId]");
request.AddParameter("client_secret", "[Your app's secret]");
request.AddParameter("scope", "https://wns.windows.com/.default");
RestResponse response = await client.ExecutePostAsync(request);
Console.WriteLine(response.Content);

Se o seu pedido for bem-sucedido, receberá uma resposta que contém o seu token no campo access_token.

{
    "token_type":"Bearer",
    "expires_in":"86399",
    "ext_expires_in":"86399",
    "expires_on":"1653771789",
    "not_before":"1653685089",
    "access_token":"[your access token]"
}

Passo 2. Enviar uma notificação bruta

Crie uma solicitação HTTP POST que contenha o token de acesso obtido na etapa anterior e o conteúdo da notificação por push que deseja enviar. O conteúdo da notificação por push será entregue ao aplicativo.

POST /?token=[The token query string parameter from your channel URL. E.g. AwYAAABa5cJ3...] HTTP/1.1
Host: dm3p.notify.windows.com
Content-Type: application/octet-stream
X-WNS-Type: wns/raw
Authorization: Bearer [your access token]
Content-Length: 46

{ Sync: "Hello from the Contoso App Service" }
var client = new RestClient("[Your channel URL. E.g. https://wns2-by3p.notify.windows.com/?token=AwYAAABa5cJ3...]");
var request = new RestRequest();
request.Method = Method.Post; 
request.AddHeader("Content-Type", "application/octet-stream");
request.AddHeader("X-WNS-Type", "wns/raw");
request.AddHeader("Authorization", "Bearer [your access token]");
request.AddBody("Notification body");
RestResponse response = await client.ExecutePostAsync(request);");

Etapa 3: enviar uma notificação de aplicativo originado na nuvem

Se você estiver interessado apenas em enviar notificações brutas, ignore esta etapa. Para enviar uma notificação de aplicação proveniente da cloud, também conhecida como notificação push toast, siga primeiro o Quickstart: Notificações de aplicação no SDK de Aplicações Windows. As notificações do aplicativo podem ser enviadas por push (enviadas da nuvem) ou enviadas localmente. O envio de uma notificação de aplicativo na nuvem é semelhante ao envio de uma notificação bruta na Etapa 2, exceto que o cabeçalho X-WNS-Type é toast, Content-Type é text/xml, e o conteúdo contém a carga XML da notificação do aplicativo. Consulte o esquema XML de notificações para obter mais informações sobre como construir a sua carga útil XML.

Crie uma solicitação HTTP POST que contenha seu token de acesso e o conteúdo da notificação de aplicativo de origem na nuvem que você deseja enviar. O conteúdo da notificação por push será entregue ao aplicativo.

POST /?token=AwYAAAB%2fQAhYEiAESPobjHzQcwGCTjHu%2f%2fP3CCNDcyfyvgbK5xD3kztniW%2bjba1b3aSSun58SA326GMxuzZooJYwtpgzL9AusPDES2alyQ8CHvW94cO5VuxxLDVzrSzdO1ZVgm%2bNSB9BAzOASvHqkMHQhsDy HTTP/1.1
Host: dm3p.notify.windows.com
Content-Type: text/xml
X-WNS-Type: wns/toast
Authorization: Bearer [your access token]
Content-Length: 180

<toast><visual><binding template="ToastGeneric"><text>Example cloud toast notification</text><text>This is an example cloud notification using XML</text></binding></visual></toast>
var client = new RestClient("https://dm3p.notify.windows.com/?token=AwYAAAB%2fQAhYEiAESPobjHzQcwGCTjHu%2f%2fP3CCNDcyfyvgbK5xD3kztniW%2bjba1b3aSSun58SA326GMxuzZooJYwtpgzL9AusPDES2alyQ8CHvW94cO5VuxxLDVzrSzdO1ZVgm%2bNSB9BAzOASvHqkMHQhsDy");
client.Timeout = -1;

var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "text/xml");
request.AddHeader("X-WNS-Type", "wns/toast");
request.AddHeader("Authorization", "Bearer <AccessToken>");
request.AddParameter("text/xml", "<toast><visual><binding template=\"ToastGeneric\"><text>Example cloud toast notification</text><text>This is an example cloud notification using XML</text></binding></visual></toast>",  ParameterType.RequestBody);
Console.WriteLine(response.Content);

Resources