Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом кратком руководстве вы создадите классическое приложение Windows, которое отправляет и получает push-уведомления с помощью пакета SDK для приложений Windows.
Предпосылки
- Начало разработки приложений Windows
- Создайте новый проект, использующий пакет SDK для приложений Windows, или используйте пакет SDK для приложений Windows в существующем проекте.
- Для использования push-уведомлений windows App SDK требуется учетной записи Azure.
- Обзор push-уведомлений
Пример приложения
В этом кратком руководстве описывается добавление поддержки push-уведомлений в приложение. См. пример кода из этого краткого руководства в контексте примеров приложений, найденных на GitHub.
Справочник по API
Справочную документацию по API для push-уведомлений можно найти в пространстве имен Microsoft.Windows.PushNotifications, см.
Настройка идентификатора приложения в Azure Active Directory (AAD)
Push-уведомления в Windows App SDK используют идентификацию из Azure Active Directory (AAD). Учетные данные Azure необходимы при запросе URI канала WNS и при запросе маркеров доступа для отправки push-уведомлений. Примечание: Мы НЕ поддерживаем push-уведомления пакета Windows App SDK через Центр партнеров Майкрософт.
Шаг 1. Создание регистрации приложения AAD
Войдите в учетную запись Azure и создайте новый ресурс регистрации приложения AAD . Выберите Новая регистрация.
Шаг 2. Укажите имя и выберите параметр многоарендности
Введите имя приложения
Для push-уведомлений требуется параметр с несколькими клиентами, поэтому выберите это.
- Дополнительные сведения об арендаторах см. в разделе Кто может войти в приложение?.
Нажмите кнопку Зарегистрировать.
Запишите идентификатор приложения (клиента) , так как это ваш Azure AppId , который вы будете использовать во время регистрации активации и запроса токена доступа.
Запишите ваш идентификаторкаталога
(клиента), так как это ваш Azure TenantId , который вы будете использовать при запросе токена доступа. Это важно
запишите идентификаторклиент регистрации приложений AAD приложения (клиента) иидентификатор каталога(клиента). Запишите ваш идентификатор объекта , так как это ваш Azure ObjectId, который вы будете использовать при запросе канала. Обратите внимание, что это НЕ идентификатор объекта, указанный на странице Essentials . Вместо этого, чтобы найти правильный идентификатор объекта , щелкните название приложения в поле управляемого приложения в локальном каталоге на странице Essentials.
Замечание
Для получения идентификатора объекта требуется субъекта-службы; если ни один из них не связан с вашим приложением, выполните действия, описанные в одной из следующих статей, чтобы создать его на портале Azure или с помощью командной строки.
Используйте Azure PowerShell для создания учетной записи службы с помощью сертификата
Шаг 3. Создание секрета для регистрации приложения
Ваш секрет будет использоваться вместе с Azure AppId/ClientId, когда вы запрашиваете токен доступа, чтобы отправлять push-уведомления.
Перейдите к сертификатам и секретам и выберите новый секрет клиента.
Это важно
Убедитесь, что вы скопируете секрет после создания и сохраните его в безопасном расположении, например Azure Key Vault. Он будет доступен только один раз сразу после создания.
Шаг 4. Сопоставьте имя семейства пакетов вашего приложения с его Azure AppId
Если ваше приложение упаковано (в том числе упаковано с внешним расположением), можно использовать этот процесс для определения имени семейства пакетов приложения (PFN) и его идентификатора приложения Azure.
Если приложение является упакованным приложением Win32, создайте запрос сопоставления имен семейства пакетов (PFN), отправив Win_App_SDK_Push@microsoft.com сообщение электронной почты с строкой темы "Запрос на сопоставление push-уведомлений пакета SDK для приложений Windows" и текст "PFN: [ваш PFN]", AppId: [your APPId], ObjectId: [your ObjectId]. Запросы на сопоставление выполняются еженедельно. Вы получите уведомление после завершения запроса на сопоставление.
Настройка приложения для получения push-уведомлений
Шаг 1. Добавьте объявления пространства имен
Добавьте пространство имен для push-уведомлений пакета SDK для Приложений Windows Microsoft.Windows.PushNotifications
.
#include <winrt/Microsoft.Windows.PushNotifications.h>
using namespace winrt::Microsoft::Windows::PushNotifications;
Шаг 2. Добавление активатора COM в манифест приложения
Это важно
Если ваше приложение неупаковано (т. е. у него отсутствует удостоверение пакета во время выполнения), перейдите к Шагу 3: Зарегистрируйтесь для получения push-уведомлений и реагируйте на них при запуске приложения.
Если приложение упаковано (включая пакет с внешним расположением): откройте 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. Регистрация и реагирование на push-уведомления при запуске приложения
Обновите метод приложения main()
, чтобы добавить следующее:
- Зарегистрируйте приложение для получения push-уведомлений, вызвав PushNotificationManager::Default().Register().
- Проверьте источник запроса активации, вызвав AppInstance::GetCurrent().GetActivatedEventArgs(). Если активация была вызвана push-уведомлением, ответьте, учитывая данные уведомления.
Это важно
Необходимо вызвать PushNotificationManager::D efault(). Зарегистрируйте перед вызовом 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. Запрос URI канала WNS и регистрация его с помощью сервера WNS
URI канала WNS — это конечные точки HTTP для отправки push-уведомлений. Каждый клиент должен запросить URI канала и зарегистрировать его на сервере WNS для получения push-уведомлений.
Замечание
Срок действия URI канала WNS истекает через 30 дней.
auto channelOperation{ PushNotificationManager::Default().CreateChannelAsync(winrt::guid("[Your app's Azure ObjectID]")) };
PushNotificationManager попытается создать URI канала, повторяя попытку в течение не более чем 15 минут. Создайте обработчик событий для ожидания завершения вызова. После завершения вызова, если он был успешным, зарегистрируйте URI на сервере 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;
}
Шаг 5. Создание и установка приложения
Используйте Visual Studio для сборки и установки приложения. Щелкните правой кнопкой мыши на файл решения в Проводнике решений и выберите Развертывание. Visual Studio создаст приложение и установит его на компьютере. Приложение можно запустить, запустив его с помощью меню "Пуск" или отладчика Visual Studio.
Отправка push-уведомления в приложение
На этом этапе все конфигурации завершено, и сервер WNS может отправлять push-уведомления клиентским приложениям. В следующих шага х дополнительные сведения см. в
Шаг 1: Запрос токена доступа
Чтобы отправить push-уведомление, сервер WNS сначала должен запросить маркер доступа. Отправьте HTTP-запрос POST с вашим Azure TenantId, Azure AppId и секретным ключом. Сведения о получении Идентификатора клиента (TenantId) Azure и Идентификатора приложения (AppId) Azure см. в разделе Получение значений идентификатора клиента и приложения для входа.
Пример 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, содержащий маркер доступа, полученный на предыдущем шаге, и содержимое push-уведомления, которое вы хотите отправить. Содержимое push-уведомления будет доставлено в приложение.
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. Отправка уведомления об облачном приложении
Если вы заинтересованы только в отправке необработанных уведомлений, игнорируйте этот шаг. Чтобы отправить уведомление приложения из облака, также известное как push-уведомление или всплывающее уведомление, сначала выполните Краткое руководство: Уведомления приложений в Windows App SDK. Уведомления приложений могут отправляться (отправляться из облака) или отправляться локально. Отправка уведомления об использовании облачного приложения аналогична отправке необработанного уведомления в
Создайте HTTP-запрос POST, содержащий маркер доступа и содержимое уведомления о облачном приложении, которое вы хотите отправить. Содержимое push-уведомления будет доставлено в приложение.
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 developer