Schnellstart: Pushbenachrichtigungen im Windows App SDK

In dieser Schnellstartanleitung erstellen Sie eine Windows-Desktopanwendung, die mithilfe des Windows App SDK Pushbenachrichtigungen sendet und empfängt.

Voraussetzungen

Beispiel-App

Diese Schnellstartanleitung führt Sie durch das Hinzufügen der Unterstützung von Pushbenachrichtigungen zu Ihrer App. Sehen Sie sich den Beispielcode aus dieser Schnellstartanleitung im Kontext der Beispiel-Apps auf GitHub an.

API-Referenz

API-Referenzdokumentation für Pushbenachrichtigungen finden Sie im Microsoft.Windows.PushNotifications- Namespace.

Konfigurieren der Identität Ihrer App in Azure Active Directory (AAD)

Pushbenachrichtigungen im Windows App SDK verwenden Identitäten aus Azure Active Directory (AAD). Azure-Anmeldedaten sind erforderlich, wenn eine WNS-Kanal-URI angefordert wird und wenn Zugriffstokens angefordert werden, um Pushbenachrichtigungen zu senden. Hinweis: Die Verwendung von Windows App SDK-Pushbenachrichtigungen mit dem Microsoft Partner Center wird NICHT unterstützt.

Schritt 1: Erstellen einer AAD-App-Registrierung

Melden Sie sich bei Ihrem Azure-Konto an und erstellen Sie eine neue Ressource zur AAD-App-Registrierung. Wählen Sie Neue Registrierung aus.

Schritt 2: Eingeben eines Namens und Auswählen einer Option für mehrere Mandanten

  1. Geben Sie einen App-Namen an.

  2. Pushbenachrichtigungen erfordern die Option für mehrere Mandanten. Wählen Sie sie also aus.

    1. Weitere Informationen zu Mandanten finden Sie unter Wer kann sich bei Ihrer App anmelden?.
  3. Wählen Sie Registrieren aus.

  4. Notieren Sie sich Ihre Anwendungs-ID (Client-ID), denn das ist Ihre Azure-AppId, die Sie beim Aktivieren der Registrierung und beim Anfordern eines Zugriffstokens brauchen.

  5. Notieren Sie sich Ihre Verzeichnis-ID (Mandanten-ID), denn das ist Ihre Azure-TenantId, ist, die Sie beim Anfordern eines Zugriffstokens brauchen.

    Wichtig

    AAD App Registration Tenant Notieren Sie sich Ihre Anwendungs-ID (Client-ID) und Verzeichnis-ID (Mandanten-ID).

  6. Notieren Sie sich Ihre Objekt-ID, denn das ist Ihre Azure-ObjectId, die Sie beim Anfordern einer Kanalanforderung brauchen. Beachten Sie, dass es sich dabei NICHT um die auf der Seite Essentials aufgeführte Objekt-ID handelt. Klicken Sie stattdessen zum Ermitteln der richtigen Objekt-ID auf der Seite Essentials im Feld Verwaltete Anwendung im lokalen Verzeichnis auf den App-Namen:

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

    Screenshot showing the Object ID field

    Hinweis

    Zum Abrufen einer Objekt-ID ist ein Dienstprinzipal erforderlich. Wenn Ihrer App kein Dienstprinzipal zugeordnet ist, können Sie ihn nach den Schritten in einem der folgenden Artikel im Azure-Portal oder über die Befehlszeile erstellen:

    Erstellen einer Azure AD-Anwendung und eines Dienstprinzipals mit Ressourcenzugriff über das Portal

    Verwenden von Azure PowerShell zum Erstellen eines Dienstprinzipals mit einem Zertifikat

Schritt 3: Erstellen eines Geheimnisses für Ihre App-Registrierung

Ihr Geheimnis wird zusammen mit Ihrer Azure-AppId/ClientId verwendet, wenn Sie ein Zugriffstoken zum Senden von Pushbenachrichtigungen anfordern.

AAD App Secret

Navigieren Sie zu Zertifikate und Geheimnisse und wählen Sie Neuer geheimer Clientschlüssel aus.

Wichtig

Sie sollten Ihr Geheimnis nach dem Erstellen unbedingt kopieren und an einem sicheren Speicherort, wie z. B. in Azure Key Vault, speichern. Es wird nur einmal direkt nach der Erstellung angezeigt.

Schritt 4: Zuordnen des Paketfamiliennamen Ihrer App zur entsprechenden Azure-AppId

Wichtig

Der Windows-Pushbenachrichtigungsdienst (WNS) ist jetzt in das Azure-Portal integriert. Die neue Registrierungsumgebung ist in der Vorschau verfügbar. Wenn Ihre App eine gepackte App ist (auch gepackt mit externem Speicherort), können Sie nach diesem Ablauf den Paketfamiliennamen (PFN) Ihrer App der entsprechenden Azure-AppId zuordnen.

Wenn Ihre App eine gepackte Win32-App ist, fordern Sie den Zugriff auf unsere neue Vorschau-Umgebung im Azure-Portal an mit einer E-Mail an Win_App_SDK_Push@microsoft.com mit der Betreffzeile „Anforderung von Windows App SDK-Pushbenachrichtigungen“ und dem Text „Azure-Abonnement: [Ihre Azure-Abonnement-ID]“. Anforderungen werden innerhalb einer Woche erledigt. Sie werden benachrichtigt, wenn Ihre Zuordnungsanforderung abgeschlossen ist.

Konfigurieren Ihrer App zum Empfangen von Pushbenachrichtigungen

Schritt 1: Hinzufügen von Namespacedeklarationen

Fügen Sie den Namespace für Windows App SDK-Pushbenachrichtigungen Microsoft.Windows.PushNotifications hinzu.

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

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

Schritt 2: Hinzufügen des COM-Aktivators zu Ihrem App-Manifest

Wichtig

Wenn Ihre App ungepackt ist (d. h. zur Laufzeit keine Paketidentität hat), fahren Sie fort mit Schritt 3: Registrieren und Antworten auf Pushbenachrichtigungen beim Starten der App.

Wenn Ihre App gepackt ist (auch gepackt mit externem Speicherort): Öffnen Sie Ihr Package.appxmanifest. Fügen Sie im <Application>-Element Folgendes hinzu. Ersetzen Sie die Werte Id, Executable und DisplayName durch die für Ihre App spezifischen Werte.

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

Schritt 3: Registrieren und Antworten auf Pushbenachrichtigungen beim Starten der App

Aktualisieren Sie die main()-Methode Ihrer App und fügen Sie Folgendes hinzu:

  1. Registrieren Sie Ihre App zum Empfangen von Pushbenachrichtigungen durch Aufrufen von PushNotificationManager::D efault().Register().
  2. Überprüfen Sie die Quelle der Aktivierungsanforderung durch Aufrufen von AppInstance::GetCurrent().GetActivatedEventArgs(). Wenn die Aktivierung von einer Pushbenachrichtigung ausgelöst wurde, antworten Sie basierend auf der Payload der Benachrichtigung.

Wichtig

Sie müssen PushNotificationManager::Default().Register aufrufen, bevor Sie AppInstance.GetCurrent.GetActivatedEventArgs aufrufen.

Das folgende Beispiel stammt aus der gepackten Beispiel-App, die auf GitHub zu finden ist.

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

Schritt 4: Anfordern eines WNS-Kanal-URI und Registrieren mit dem WNS-Server

WNS-Kanal-URIs sind die HTTP-Endpunkte zum Senden von Pushbenachrichtigungen. Jeder Client muss einen Kanal-URI anfordern und beim WNS-Server registrieren, um Pushbenachrichtigungen zu empfangen.

Hinweis

WNS-Kanal-URIs laufen nach 30 Tagen ab.

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

Der PushNotificationManager versucht, einen Kanal-URI zu erstellen, und wiederholt den Versuch automatisch für maximal 15 Minuten. Erstellen Sie einen Ereignishandler, um auf den Abschluss des Aufrufs zu warten. Sobald der Aufruf erfolgreich abgeschlossen ist, registrieren Sie den URI beim WNS-Server.

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

Schritt 5: Erstellen und Installieren der App

Verwenden Sie Visual Studio zum Erstellen und Installieren Ihrer App. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Projektmappendatei und wählen Sie Bereitstellen aus. Visual Studio erstellt Ihre App und installiert sie auf Ihrem Computer. Sie können die App ausführen, indem Sie sie über das Startmenü oder den Visual Studio-Debugger starten.

Senden einer Pushbenachrichtigungen an Ihre App

An diesem Punkt ist die gesamte Konfiguration abgeschlossen, und der WNS-Server kann Pushbenachrichtigungen an Client-Apps senden. In den folgenden Schritten finden Sie weitere Details unter Anforderungs- und Antwortheader des Pushbenachrichtigungsservers.

Schritt 1: Anfordern eines Zugriffstokens

Zum Senden einer Pushbenachrichtigung muss der WNS-Server zuerst ein Zugriffstoken anfordern. Senden Sie eine HTTP POST-Anforderung mit Ihrer Azure-TenantId, Azure-AppId und ihrem Geheimnis. Informationen zum Abrufen der Azure-TenantId und Azure-AppId finden Sie unter Abrufen der Werte für Mandanten-ID und App-ID für die Anmeldung.

Beispiel für eine HTTP-Anforderung:

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/

C#-Beispielanforderung:

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

Wenn Ihre Anforderung erfolgreich ist, erhalten Sie eine Antwort, die Ihr Token im Feld access_token enthält.

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

Schritt 2. Senden einer unformatierten Benachrichtigung

Erstellen Sie eine HTTP POST-Anforderung mit dem Zugriffstoken, das Sie im vorherigen Schritt abgerufen haben, und dem zu sendenden Inhalt der Pushbenachrichtigung. Der Inhalt der Pushbenachrichtigung wird an die App übermittelt.

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

Schritt 3: Senden einer cloudbasierten App-Benachrichtigung

Wenn Sie nur unformatierte Benachrichtigungen senden möchten, können Sie diesen Schritt außer Acht lassen. Zum Senden einer cloudbasierten App-Benachrichtigung, auch als Push-Popupbenachrichtigung bezeichnet, aus der Cloud zu senden, befolgen Sie zunächst die Anweisungen unter Schnellstart: App-Benachrichtigungen im Windows App SDK. App-Benachrichtigungen können entweder per Push (gesendet aus der Cloud) oder lokal gesendet werden. Das Senden einer cloudbasierten App-Benachrichtigung ähnelt dem Senden einer unformatierten Benachrichtigung in Schritt 2, aber der Header X-WNS-Typ ist toast, der Inhaltstyp ist text/xml und der Inhalt enthält die XML-Payload der App-Benachrichtigung. Weitere Informationen zum Erstellen ihrer XML-Payload finden Sie im XML-Schema für Benachrichtigungen.

Erstellen Sie eine HTTP POST-Anforderung mit Ihrem Zugriffstoken und dem zu sendenden Inhalt der cloudbasierten App-Benachrichtigung. Der Inhalt der Pushbenachrichtigung wird an die App übermittelt.

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

Ressourcen