Démarrage rapide : notifications Push dans le SDK d’application Windows

Dans ce guide de démarrage rapide, vous allez créer une application Windows de bureau qui envoie et reçoit des notifications d’application locale, également appelées notifications toast, à l’aide duSDK d'application Windows.

Prérequis

Exemple d’application

Ce guide de démarrage rapide vous guide tout au long de l’ajout de la prise en charge des notifications Push à votre application. Consultez l’exemple de code de ce guide de démarrage rapide dans le contexte dans les exemples d’applications trouvés sur GitHub.

Informations de référence sur l'API

Pour obtenir la documentation de référence sur les API pour les notifications d’application, consultez Espace de noms Microsoft.Windows.AppNotifications.

Configurer l'identité de votre application dans Azure Active Directory (AAD)

Les notifications Push dans le Kit de développement logiciel (SDK) d’application Windows utilisent des identités à partir d’Azure Active Directory (AAD). Les informations d’identification Azure sont requises lors de la demande d’un URI de canal WNS et lors de la demande de jetons d’accès afin d’envoyer des notifications Push. Remarque : Nous ne prenons PAS en charge l’utilisation des notifications Push du SDK d'application Windows avec l’Espace partenaires Microsoft.

Étape 1 : Créer une inscription d’application dans BindID

Connectez-vous à votre compte Azure et créez une ressource AAD App Registration. Sélectionnez Nouvelle inscription.

Étape 2 : Fournir un nom et sélectionner une option multilocataire

  1. Fournissez un nom d’application.

  2. Les notifications Push nécessitent l’option multilocataire. Sélectionnez-la.

    1. Pour plus d’informations sur les clients, consultez Qui pouvez vous connecter à votre application ?.
  3. Sélectionnez Inscrire

  4. Notez votre ID d’application (client), car il s’agit de votre Azure AppId Azure que vous utiliserez lors de l’inscription de l’activation et de la demande de jeton d’accès.

  5. Notez votre ID d’annuaire (tenant), car il s’agit de votre Azure TenantId que vous utiliserez lors de la demande d’un jeton d’accès.

    Important

    AAD App Registration Tenant Prenez note de votre ID Application (client) et de votre ID annuaire (tenant).

  6. Notez votre ID objet, car il s’agit de votre Azure ObjectId que vous utiliserez lors de la demande d’un canal. Notez qu’il ne s’agit PAS de l’ID objet répertorié dans la page Essentials. Au lieu de cela, pour rechercher l’ID objet correct, cliquez sur le nom de l’application gérée dans le champ Annuaire local de la page Essentials :

    Screenshot showing the Managed application in local directory option on the Essentials page

    Screenshot showing the Object ID field

    Remarque

    Un principal de service est requis pour obtenir un ID d’objet, s’il n’en existe pas associé à votre application, suivez les étapes de l’un des articles suivants pour en créer un dans le Portail Azure ou à l’aide de la ligne de commande :

    Utiliser le portail pour créer une application Azure AD et un principal de service ayant accès aux ressources

    Utiliser Azure PowerShell pour créer un principal du service avec un certificat

Étape 3 : créer un secret client pour l’inscription de l’application

Votre secret sera utilisé avec votre Azure AppId/ClientId lors de la demande d’un jeton d’accès pour envoyer des notifications Push.

AAD App Secret

Accédez à Certificats et secrets et sélectionnez Nouvelle clé secrète client.

Important

Veillez à copier votre secret une fois créé et à le stocker dans un emplacement sûr, comme Azure Key Vault. Il ne sera visible qu’une seule fois après la création.

Étape 4 : Mapper le nom de la famille de packages de votre application à son Azure AppId

Important

Windows Push Notification Service (WNS) est désormais intégré au portail Azure. L’expérience de préversion pour les inscriptions d’applications est disponible. Si vous êtes une application empaquetée (y compris empaquetée avec un emplacement externe), vous pouvez utiliser ce flux pour mapper le nom de famille de packages (PFN) de votre application et son AppId Azure.

Si votre application est une application Win32 empaquetée, demandez l’accès à notre nouvelle expérience de préversion du portail Azure en envoyant Win_App_SDK_Push@microsoft.com un e-mail à l’aide de la ligne d’objet « Demande push du SDK d’application Windows » et du corps « Abonnement Azure : [votre ID d’abonnement Azure] ». Les demandes sont effectuées toutes les semaines. Vous serez averti une fois votre demande de mappage terminée.

Configurer votre application pour recevoir des notifications Push de l’Espace partenaires

Étape 1 : Ajouter des déclarations d’espaces de noms

Ajoutez l’espace de noms pour les notifications push SDK d'application Windows Microsoft.Windows.PushNotifications.

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

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

Étape 2 : Ajouter votre activateur COM au manifeste de votre application

Important

Si votre application n’est pas empaquetée (c’est-à-dire qu’elle n’a pas d’identité de package au moment de l’exécution), passez à l’Étape 3 : S’inscrire pour gérer une notification d’application.

Si votre application est empaquetée (y compris empaquetée avec un emplacement externe) : ouvrez votre Package.appxmanifest. Ajoutez le code XML suivant dans l’élément <Application>. Remplacez les valeurs Id, Executable et DisplayName les valeurs par celles spécifiques à votre application.

<!--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>    

Étape 3 : S’inscrire et répondre aux notifications Push au démarrage de l’application

Ajoutez la méthode main() suivante à votre classe.

  1. Inscrivez votre application pour recevoir des notifications Push en appelant PushNotificationManager ::D efault(). Register().
  2. Vérifiez la source de la demande d’activation en appelant AppInstance ::GetCurrent(). GetActivatedEventArgs(). Si l’activation a été déclenchée à partir d’une notification Push, répondez en fonction de la charge utile de la notification.

Important

Vous devez appeler AppNotificationManager::Default().Register avant d’appeler AppInstance.GetCurrent.GetActivatedEventArgs.

L’exemple suivant provient de l’exemple d’application empaquetée trouvée sur GitHub.

// cpp-console.cpp
#include "pch.h"
#include <iostream>
#include <winrt/Microsoft.Windows.PushNotifications.h>
#include <winrt/Microsoft.Windows.AppLifecycle.h>
#include <winrt/Windows.Foundation.h>
#include <wil/result.h>
#include <wil/cppwinrt.h>


using namespace winrt;
using namespace Windows::Foundation;

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

winrt::guid remoteId{ "7edfab6c-25ae-4678-b406-d1848f97919a" }; // Replace this with your own Azure ObjectId



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

int main()
{
    // Setup an event handler, so we can receive notifications in the foreground while the app is running.
    SubscribeForegroundEventHandler();

    PushNotificationManager::Default().Register();

    auto args{ AppInstance::GetCurrent().GetActivatedEventArgs() };
    switch (args.Kind())
    {
        // When it is launched normally (by the users, or from the debugger), the sample requests a WNS Channel URI and
        // displays it, then waits for notifications. This user can take a copy of the WNS Channel URI and use it to send
        // notifications to the sample
        case ExtendedActivationKind::Launch:
        {
            // Checks to see if push notifications are supported. Certain self-contained apps may not support push notifications by design
            if (PushNotificationManager::IsSupported())
            {
                // 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
            {
                // App implements its own custom socket here to receive messages from the cloud since Push APIs are unsupported.
            }
        }
        break;

        // When it is activated from a push notification, the sample only displays the notification.
        // It doesn’t register for foreground activation of perform any other actions
        // because background activation is meant to let app perform only small tasks in order to preserve battery life.
        case ExtendedActivationKind::Push:
        {
            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;
    }

    // We do not call PushNotificationManager::UnregisterActivator
    // because then we wouldn't be able to receive background activations, once the app has closed.
    // Call UnregisterActivator once you don't want to receive push notifications anymore.
}

Étape 4 : Demander un URI de canal WNS et l’inscrire auprès du serveur WNS

Les URI de canal WNS sont les points de terminaison HTTP pour l’envoi de notifications Push. Chaque client doit demander un URI de canal et l’inscrire auprès du serveur WNS pour recevoir des notifications Push.

Remarque

Les URI de canal WNS expirent après 30 jours.

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

PushNotificationManager tente de créer un URI de canal, réessayant automatiquement pendant plus de 15 minutes. Créez un gestionnaire d’événements pour attendre la fin de l’appel. Une fois l’appel terminé, s’il a réussi, inscrivez l’URI auprès du serveur WNS.

// cpp-console.cpp

winrt::Windows::Foundation::IAsyncOperation<PushNotificationChannel> RequestChannelAsync()
{
    // To obtain an AAD RemoteIdentifier for your app,
    // follow the instructions on https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app
    auto channelOperation = PushNotificationManager::Default().CreateChannelAsync(remoteId);

    // Setup the inprogress 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;
}

Étape 5 : générer et exécuter votre application

Utilisez Visual Studio Code pour générer et exécuter votre application. Cliquez avec le bouton droit sur la solution dans l’Explorateur de solutions, puis sélectionnez Déployer. Visual Studio génère votre application et l’installe sur votre ordinateur. Vous pouvez exécuter l’application en la lançant via le menu Démarrer ou le débogueur Visual Studio.

Envoi d’une notification vers votre application

À ce stade, toute la configuration est terminée et le serveur WNS peut envoyer des notifications Push aux applications clientes. Dans les étapes suivantes, reportez-vous aux en-têtes de demande et de réponse du serveur de notification Push pour plus de détails.

Étape 1 : demander un jeton d’accès

Pour envoyer une notification Push, le serveur WNS doit d’abord demander un jeton d’accès. Envoyez une requête HTTP POST avec votre Azure TenantId, Azure AppId et votre secret. Pour plus d’informations sur la récupération d’Azure TenantId et d’Azure AppId, consultez Obtenir les valeurs d’ID de locataire et d’application pour la connexion.

Exemple de requête 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/

Exemple de requête :

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

Si votre demande réussit, vous recevrez une réponse contenant votre jeton dans le champ access_token.

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

Étape 2. Envoi d’une notification

Créez une requête HTTP POST qui contient le jeton d’accès que vous avez obtenu à l’étape précédente et le contenu de la notification Push que vous souhaitez envoyer. Le contenu de la notification Push est remis à l’application.

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);");

Étape 3 : envoyer une notification d’application de source cloud

Si vous souhaitez uniquement envoyer des notifications brutes, ignorez cette étape. Pour envoyer une notification d'app dans le cloud, également connue sous le nom de notification push toast, suivez d'abord Démarrage rapide : notifications d'applications dans SDK d'application Windows. Les notifications d’application peuvent être envoyées (à partir du cloud) ou envoyées localement. L’envoi d’une notification d’application source à partir du cloud est similaire à l’envoi d’une notification brute, sauf que l’en-tête X-WNS-Type est , Content-Type toast est et le contenu contient la charge utile XML de notification d’application. Vous pouvez en savoir plus à ce sujet icitext/xml. Pour plus d’informations sur la construction de votre charge utile XML, consultez le schéma XML notifications.

Créez une requête HTTP POST qui contient votre jeton d’accès et le contenu de la notification d’application source dans le cloud que vous souhaitez envoyer. Le contenu de la notification Push est remis à l’application.

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

Ressources