このクイック スタートでは、Windows App SDK を使用してプッシュ通知を送受信するデスクトップ Windows アプリケーションを作成します。
[前提条件]
- Windows アプリ の開発を開始する
- Windows アプリ SDK を使う新しいプロジェクトを作成するか、既存のプロジェクトで Windows アプリ SDK を使います
- Windows App SDK プッシュ通知を使用するには、 Azure アカウント が必要です。
- プッシュ通知の概要を読む
サンプル アプリ
このクイック スタートでは、プッシュ通知のサポートをアプリに追加する手順について説明します。 GitHubにあるサンプル アプリのコンテキストで、このクイック スタートのコード例
API リファレンス
プッシュ通知の API リファレンス ドキュメントについては、 Microsoft.Windows.PushNotifications 名前空間を参照してください。
Azure Active Directory (AAD) でアプリの ID を構成する
Windows App SDK のプッシュ通知では、Azure Active Directory (AAD) の ID が使用されます。 WNS チャネル URI を要求するとき、およびプッシュ通知を送信するためにアクセス トークンを要求する場合は、Azure 資格情報が必要です。 注: Microsoft パートナー センターでの Windows App SDK プッシュ通知の使用はサポートしていません。
手順 1: AAD アプリの登録を作成する
Azure アカウントにログインして、新しい AAD アプリ登録 リソース を作成します。 [新規登録] を選択します。
手順 2: 名前を指定し、マルチテナント オプションを選択する
アプリケーションの名前を指定します。
プッシュ通知にはマルチテナント オプションが必要なので、これを選択します。
- テナントの詳細については、「 アプリにサインインできるユーザー」を参照してください。
[登録] を選択します
アプリケーション (クライアント) ID に注意してください。これは、アクティブ化の登録とアクセス トークンの要求時に使用する Azure AppId です。
アクセス トークンを要求するときに使用する Azure TenantId であるため、ディレクトリ (テナント) ID を書き留めます。
Von Bedeutung
アプリケーション (クライアント) ID とディレクトリ (テナント) ID を書き留めます。
オブジェクト IDを書き留めてください。これは、チャネルリクエストを送信するときに使用する、Azure オブジェクト ID です。 これは、[ 要点 ] ページに一覧表示されているオブジェクト ID ではないことに注意してください。 代わりに、正しいオブジェクト ID を見つけるには、[要点] ページの [ローカル ディレクトリのマネージド アプリケーション] フィールドでアプリ名をクリックします。
注
オブジェクト ID を取得するには 、サービス プリンシパル が必要です。アプリに関連付けられていない場合は、次のいずれかの記事の手順に従って、Azure portal またはコマンド ラインで作成します。
手順 3: アプリ登録用のシークレットを作成する
プッシュ通知を送信するアクセス トークンを要求するときに、シークレットが Azure AppId/ClientId と共に使用されます。
認証と秘密の質問 に移動し、 新しいクライアントの秘密の質問を選択します。
Von Bedeutung
作成したシークレットをコピーし、Azure Key Vault などの安全な場所に保存してください。 作成直後に表示できるのは 1 回だけです。
手順 4: アプリのパッケージ ファミリ名を Azure AppId にマップする
アプリがパッケージ化されている場合 (外部の場所でパッケージ化されている場合を含む)、このフローを使用して、アプリのパッケージ ファミリ名 (PFN) とその Azure AppId をマップできます。
アプリがパッケージ化された Win32 アプリの場合は、件名に "Windows App SDK プッシュ通知マッピング要求" と本文 "PFN: [your PFN]"、AppId: [your APPId]、ObjectId: [your ObjectId]を含む Win_App_SDK_Push@microsoft.com を電子メールで送信して、パッケージ ファミリ名 (PFN) マッピング要求を作成します。 マッピング要求は週単位で完了します。 マッピング要求が完了すると、通知が表示されます。
プッシュ通知を受信するようにアプリを構成する
手順 1: 名前空間宣言を追加する
Windows App SDK のプッシュ通知に対する名前空間 Microsoft.Windows.PushNotifications
を追加します。
#include <winrt/Microsoft.Windows.PushNotifications.h>
using namespace winrt::Microsoft::Windows::PushNotifications;
手順 2: COM アクティベーターをアプリのマニフェストに追加する
Von Bedeutung
アプリがパッケージ化されていない (つまり、実行時にパッケージ ID がない) 場合は、「 手順 3: アプリの起動時にプッシュ通知に登録して応答する」に進みます。
アプリがパッケージ化されている場合 (外部の場所でパッケージ化を含む): Package.appxmanifest を開きます。
<Application>
要素内に次のコードを追加します。
Id
、Executable
、およびDisplayName
の値を、アプリに固有の値に置き換えます。
<!--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>
手順 3: アプリの起動時にプッシュ通知に登録して応答する
アプリの main()
メソッドを更新して、次のコードを追加します。
- PushNotificationManager::D efault() を呼び出して、プッシュ通知を受信するようにアプリを登録します。Register().
- AppInstance::GetCurrent() を呼び出して、アクティブ化要求のソースを確認します。GetActivatedEventArgs(). プッシュ通知からアクティブ化がトリガーされた場合は、通知のペイロードに基づいて応答します。
Von Bedeutung
PushNotificationManager::Default().Register を呼び出す必要があります。これは、AppInstance.GetCurrent.GetActivatedEventArgsを呼び出す前に行ってください。
次のサンプルは、 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.
}
手順 4: WNS チャネル URI を要求し、WNS サーバーに登録する
WNS チャネル URI は、プッシュ通知を送信するための HTTP エンドポイントです。 各クライアントはチャネル URI を要求し、それを WNS サーバーに登録してプッシュ通知を受信する必要があります。
注
WNS チャネル URI の有効期限は 30 日後です。
auto channelOperation{ PushNotificationManager::Default().CreateChannelAsync(winrt::guid("[Your app's Azure ObjectID]")) };
PushNotificationManager はチャネル URI の作成を試み、15 分以内に自動的に再試行します。 呼び出しが完了するまで待機するイベント ハンドラーを作成します。 呼び出しが完了したら、成功した場合は、WNS サーバーに URI を登録します。
// 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;
}
手順 5: アプリをビルドしてインストールする
Visual Studio を使用してアプリをビルドしてインストールします。 ソリューション エクスプローラーでソリューション ファイルを右クリックし、デプロイを選択します。 Visual Studio によってアプリがビルドされ、コンピューターにインストールされます。 アプリを実行するには、スタート メニューまたは Visual Studio デバッガーを使用してアプリを起動します。
アプリにプッシュ通知を送信する
この時点で、すべての構成が完了し、WNS サーバーはクライアント アプリにプッシュ通知を送信できます。 次の手順では、 プッシュ通知サーバーの要求ヘッダーと応答ヘッダー を参照して詳細を確認します。
手順 1: アクセス トークンを要求する
プッシュ通知を送信するには、まず WNS サーバーがアクセス トークンを要求する必要があります。 Azure TenantId、Azure AppId、シークレットを使用して HTTP POST 要求を送信します。 Azure TenantId と Azure AppId の取得の詳細については、 サインインのテナントとアプリ ID の値の取得に関するページを参照してください。
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/
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);
要求が成功すると、 access_token フィールドにトークンを含む応答が返されます。
{
"token_type":"Bearer",
"expires_in":"86399",
"ext_expires_in":"86399",
"expires_on":"1653771789",
"not_before":"1653685089",
"access_token":"[your access token]"
}
手順 2. 未加工の通知を送信する
前の手順で取得したアクセス トークンと送信するプッシュ通知の内容を含む HTTP POST 要求を作成します。 プッシュ通知の内容がアプリに配信されます。
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);");
手順 3: クラウドソースのアプリ通知を送信する
未加工の通知のみを送信する場合は、この手順を無視してください。 クラウドソースのアプリ通知 (プッシュ トースト通知とも呼ばれます) を送信するには、まず クイック スタート: Windows App SDK のアプリ通知に従います。 アプリ通知は、プッシュ (クラウドから送信) することも、ローカルに送信することもできます。 クラウドソースのアプリ通知の送信は 、手順 2 で生の通知を送信するのと似ていますが、 X-WNS-Type ヘッダーが toast
、 Content-Type が text/xml
され、コンテンツにアプリ通知 XML ペイロードが含まれている点が異なります。 XML ペイロードを構築する方法の詳細については、 Notifications XML スキーマ を参照してください。
アクセス トークンと、送信するクラウドソースのアプリ通知の内容を含む HTTP POST 要求を作成します。 プッシュ通知の内容がアプリに配信されます。
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);
リソース
- Windows プッシュ通知サービス (WNS)
- GitHubでのプッシュ通知のサンプルコード
- Microsoft.Windows.PushNotifications API の詳細
- GitHub でプッシュ通知仕様を
する - トーストコンテンツ
- Notifications XML スキーマ
Windows developer