Обзор служб push-уведомлений Windows (WNS)

Службы push-уведомлений Windows (WNS) позволяют сторонним разработчикам отправлять всплывающие сообщения, плитки, эмблемы и необработанные обновления из собственной облачной службы. Это обеспечивает энергоэффективный и надежный механизм передачи пользователям свежих обновлений.

Как это работает

На следующей схеме показан полный поток данных для отправки push-уведомления. Он включает следующие действия:

  1. Приложение запрашивает канал push-уведомлений из WNS.
  2. Windows просит WNS создать канал уведомлений. Этот канал возвращается на вызывающее устройство в виде универсального идентификатора ресурса (URI).
  3. URI канала уведомлений возвращается WNS в приложение.
  4. Приложение отправляет универсальный код ресурса (URI) в собственную облачную службу. Затем вы сохраняете универсальный код ресурса (URI) в собственной облачной службе, чтобы получить доступ к URI при отправке уведомлений. Универсальный код ресурса (URI) — это интерфейс между собственным приложением и собственной службой; Это ваша ответственность за реализацию этого интерфейса с безопасными и безопасными веб-стандартами.
  5. Когда у облачной службы есть обновление для отправки, он уведомляет WNS с помощью URI канала. Это делается путем выдачи HTTP-запроса POST, включая полезные данные уведомления, по протоколу SSL. Для этого шага требуется проверка подлинности.
  6. WNS получает запрос и направляет уведомление на соответствующее устройство.

wns data flow diagram for push notification

Регистрация приложения и получение учетных данных для облачной службы

Прежде чем отправлять уведомления с помощью WNS, приложение должно быть зарегистрировано на панели мониторинга Магазина, как описано здесь.

Запрос канала уведомлений

Когда приложение, которое может получать push-уведомления, запускается, он должен сначала запросить канал уведомлений через CreatePushNotificationChannelForApplicationAsync. Полное обсуждение и пример кода см. в разделе "Как запрашивать, создавать и сохранять канал уведомлений". Этот API возвращает URI канала, который однозначно связан с вызывающим приложением и его плиткой, и с помощью которого можно отправлять все типы уведомлений.

После успешного создания URI канала приложение отправляет его в облачную службу вместе с любыми метаданными для конкретного приложения, которые должны быть связаны с этим URI.

Важные примечания

  • Мы не гарантируем, что универсальный код ресурса (URI) канала уведомлений для приложения всегда останется неизменным. Мы советуем приложению запрашивать новый канал при каждом запуске и обновлении службы при изменении URI. Разработчик никогда не должен изменять URI канала и должен рассматривать его как черную строку. В настоящее время срок действия URI канала истекает через 30 дней. Если приложение Windows 10 периодически продлевает свой канал в фоновом режиме, вы можете скачать пример push-уведомлений и периодические уведомления для Windows 8.1 и повторно использовать его исходный код и /или шаблон, который он демонстрирует.
  • Интерфейс между облачной службой и клиентским приложением реализуется разработчиком. Мы рекомендуем приложению пройти процесс проверки подлинности с помощью собственной службы и передать данные по защищенному протоколу, например HTTPS.
  • Важно, чтобы облачная служба всегда гарантирует, что URI канала использует домен "notify.windows.com". Служба никогда не должна отправлять push-уведомления в канал на любой другой домен. Если обратный вызов для вашего приложения когда-либо скомпрометирован, злоумышленник может отправить URI канала в spoof WNS. Не проверяя домен, облачная служба может потенциально раскрывать информацию этому злоумышленнику. Поддомен канала URI канала подлежит изменению и не следует учитывать при проверке URI канала.
  • Если облачная служба пытается доставить уведомление в канал с истекшим сроком действия, WNS вернет код ответа 410. В ответ на этот код служба больше не должна пытаться отправлять уведомления в этот универсальный код ресурса (URI).

Проверка подлинности облачной службы

Чтобы отправить уведомление, облачная служба должна проходить проверку подлинности через WNS. Первый шаг в этом процессе возникает при регистрации приложения на панели мониторинга Microsoft Store. Во время регистрации приложение получает идентификатор безопасности пакета (SID) и секретный ключ. Эта информация используется облачной службой для проверки подлинности с помощью WNS.

Схема проверки подлинности WNS реализуется с помощью профиля учетных данных клиента из протокола OAuth 2.0 . Облачная служба проходит проверку подлинности с помощью WNS, указав свои учетные данные (идентификатор безопасности пакета и секретный ключ). В обратном случае он получает маркер доступа. Этот маркер доступа позволяет облачной службе отправлять уведомление. Маркер требуется для каждого запроса уведомления, отправленного в WNS.

На высоком уровне информационная цепочка выглядит следующим образом:

  1. Облачная служба отправляет свои учетные данные в WNS по протоколу HTTPS после протокола OAuth 2.0. Это выполняет проверку подлинности службы с помощью WNS.
  2. WNS возвращает маркер доступа, если проверка подлинности выполнена успешно. Этот маркер доступа используется во всех последующих запросах уведомлений до истечения срока действия.

wns diagram for cloud service authentication

При проверке подлинности с помощью WNS облачная служба отправляет HTTP-запрос по протоколу SSL. Параметры предоставляются в формате application/x-www-for-urlencoded. Укажите идентификатор безопасности пакета в поле "client_id" и секретный ключ в поле "client_secret", как показано в следующем примере. Дополнительные сведения о синтаксисе см. в справочнике по запросу маркера доступа.

Примечание.

Это просто пример, а не вырезанный и вставленный код, который можно успешно использовать в собственном коде. 

 POST /accesstoken.srf HTTP/1.1
 Content-Type: application/x-www-form-urlencoded
 Host: https://login.live.com
 Content-Length: 211
 
 grant_type=client_credentials&client_id=ms-app%3a%2f%2fS-1-15-2-2972962901-2322836549-3722629029-1345238579-3987825745-2155616079-650196962&client_secret=Vex8L9WOFZuj95euaLrvSH7XyoDhLJc7&scope=notify.windows.com

WNS проходит проверку подлинности облачной службы, и при успешном выполнении отправляет ответ "200 ОК". Маркер доступа возвращается в параметрах, включенных в текст ответа HTTP, с помощью типа носителя application/json. После получения маркера доступа служба готова отправлять уведомления.

В следующем примере показан успешный ответ проверки подлинности, включая маркер доступа. Дополнительные сведения о синтаксисе см. в заголовках запросов и ответов службы push-уведомлений.

 HTTP/1.1 200 OK   
 Cache-Control: no-store
 Content-Length: 422
 Content-Type: application/json
 
 {
     "access_token":"EgAcAQMAAAAALYAAY/c+Huwi3Fv4Ck10UrKNmtxRO6Njk2MgA=", 
     "token_type":"bearer"
 }

Важные примечания

  • Протокол OAuth 2.0, поддерживаемый в этой процедуре, соответствует черновику версии 16.
  • Запрос OAuth для комментариев (RFC) использует термин "клиент" для ссылки на облачную службу.
  • При завершении проекта OAuth могут возникнуть изменения в этой процедуре.
  • Маркер доступа можно повторно использовать для нескольких запросов уведомлений. Это позволяет облачной службе проходить проверку подлинности только один раз для отправки большого количества уведомлений. Однако при истечении срока действия маркера доступа облачная служба должна снова пройти проверку подлинности, чтобы получить новый маркер доступа.

Отправка уведомления

Используя универсальный код ресурса (URI) канала, облачная служба может отправлять уведомление при каждом обновлении для пользователя.

Описанный выше маркер доступа можно повторно использовать для нескольких запросов уведомлений; Облачный сервер не требуется запрашивать новый маркер доступа для каждого уведомления. Если срок действия маркера доступа истек, запрос уведомления вернет ошибку. Мы рекомендуем не пытаться повторно отправить уведомление более одного раза, если маркер доступа отклонен. При возникновении этой ошибки потребуется запросить новый маркер доступа и повторно отправить уведомление. Точный код ошибки см. в разделе "Коды ответов push-уведомлений".

  1. Облачная служба отправляет HTTP POST в URI канала. Этот запрос должен быть выполнен по протоколу SSL и содержит необходимые заголовки и полезные данные уведомления. Заголовок авторизации должен содержать полученный маркер доступа для авторизации.

    Ниже показан пример запроса. Дополнительные сведения о синтаксисе см . в кодах ответов push-уведомлений.

    Дополнительные сведения о создании полезных данных уведомления см . в кратком руководстве по отправке push-уведомления. Полезные данные плитки, всплывающего уведомления или push-уведомления значка предоставляются как XML-содержимое, соответствующее определенной схеме адаптивных плиток или схеме устаревших плиток. Полезные данные необработанного уведомления не имеют указанной структуры. Оно строго определено приложением.

     POST https://cloud.notify.windows.com/?token=AQE%bU%2fSjZOCvRjjpILow%3d%3d HTTP/1.1
     Content-Type: text/xml
     X-WNS-Type: wns/tile
     Authorization: Bearer EgAcAQMAAAAALYAAY/c+Huwi3Fv4Ck10UrKNmtxRO6Njk2MgA=
     Host: cloud.notify.windows.com
     Content-Length: 24
    
     <body>
     ....
    
  2. WNS отвечает на то, что уведомление получено и будет доставлено по следующей доступной возможности. Однако WNS не предоставляет сквозное подтверждение того, что ваше уведомление получено устройством или приложением.

На этой схеме показан поток данных:

wns diagram for sending a notification

Важные примечания

  • WNS не гарантирует надежность или задержку уведомления.
  • Уведомления никогда не должны включать конфиденциальные, конфиденциальные или персональные данные.
  • Чтобы отправить уведомление, облачная служба должна сначала пройти проверку подлинности с помощью WNS и получить маркер доступа.
  • Маркер доступа позволяет облачной службе отправлять уведомления в одно приложение, для которого был создан маркер. Один маркер доступа нельзя использовать для отправки уведомлений в нескольких приложениях. Таким образом, если облачная служба поддерживает несколько приложений, она должна предоставить правильный маркер доступа для приложения при отправке уведомления в каждый URI канала.
  • Если устройство находится в автономном режиме, по умолчанию WNS будет хранить один из каждого типа уведомления (плитки, индикатора событий, всплывающих элементов) для каждого URI канала и без необработанных уведомлений.
  • В сценариях, когда содержимое уведомления персонализировано пользователю, WNS рекомендует немедленно отправлять эти обновления при получении. Примерами этого сценария являются обновления веб-канала социальных сетей, приглашения на мгновенные сообщения, уведомления о новых сообщениях или оповещения. В качестве альтернативы можно использовать сценарии, в которых одно и то же универсальное обновление часто поставляется в большое подмножество пользователей; например, погода, акции и новости обновления. Рекомендации по WNS указывают, что частота этих обновлений должна составлять не более одного каждые 30 минут. Конечный пользователь или WNS могут определять более частые регулярные обновления, которые будут оскорбительными.
  • Платформа уведомлений Windows поддерживает периодическое подключение к данным с WNS для поддержания работоспособности сокета. Если нет приложений, запрашивающих или использующих каналы уведомлений, сокет не будет создан.

Истечение срока действия уведомлений плитки и индикатора событий

По умолчанию срок действия уведомлений плитки и значка истекает через три дня после скачивания. По истечении срока действия уведомления содержимое удаляется из плитки или очереди и больше не отображается пользователю. Рекомендуется задать срок действия (с помощью времени, которое имеет смысл для приложения) на всех уведомлениях плитки и индикаторов событий, чтобы содержимое плитки не сохранялось дольше, чем это актуально. Явное время окончания срока действия необходимо для содержимого с определенным сроком существования. Это также гарантирует удаление устаревшего содержимого, если облачная служба перестает отправлять уведомления, или если пользователь отключается от сети в течение длительного периода.

Облачная служба может задать срок действия каждого уведомления, задав заголовок HTTP X-WNS-TTL, чтобы указать время (в секундах), которое ваше уведомление останется действительным после отправки. Дополнительные сведения см. в заголовках запросов и ответов службы push-уведомлений.

Например, во время активного торгового дня фондового рынка можно установить срок действия обновления цен на акции в два раза больше, чем интервал отправки (например, через час после получения, если вы отправляете уведомления каждые полчаса). В другом примере приложение новостей может определить, что один день является подходящим временем истечения срока действия для ежедневного обновления плитки новостей.

Push-уведомления и экономия батареи

Экономия батареи расширяет время работы батареи путем ограничения фонового действия на устройстве. Windows 10 позволяет пользователю настроить экономию заряда батареи автоматически, когда заряд батареи снижается ниже указанного порогового значения. Если экономия батареи включена, получение push-уведомлений отключено для экономии энергии. Но есть несколько исключений для этого. Следующие параметры экономии батареи Windows 10 (найденные в приложении Параметры) позволяют приложению получать push-уведомления даже при включении экономии батареи.

  • Разрешить push-уведомления из любого приложения во время экономии батареи: этот параметр позволяет всем приложениям получать push-уведомления во время сохранения батареи. Обратите внимание, что этот параметр применяется только к Windows 10 для классических выпусков (Home, Pro, Enterprise и Education).
  • Всегда разрешено: этот параметр позволяет определенным приложениям работать в фоновом режиме, пока экономия батареи включена, включая получение push-уведомлений. Этот список поддерживается пользователем вручную.

Нет способа проверка состояние этих двух параметров, но вы можете проверка состояние экономии батареи. В Windows 10 используйте свойство EnergySaverStatus для проверка состояния экономии батареи. Ваше приложение также может использовать событие EnergySaverStatusChanged для прослушивания изменений в экономии батареи.

Если ваше приложение сильно зависит от push-уведомлений, рекомендуется уведомлять пользователей о том, что они могут не получать уведомления во время экономии батареи и упростить настройку параметров экономии батареи. Используя схему URI URI параметров экономии батареи в Windows 10, ms-settings:batterysaver-settingsвы можете предоставить удобную ссылку на приложение Параметры.

Совет

При уведомлении пользователя о параметрах экономии батареи рекомендуется предоставить способ подавления сообщения в будущем. Например, dontAskMeAgainBox проверка box в следующем примере сохраняет предпочтения пользователя в local Параметры.

Ниже приведен пример того, как проверка включена ли экономия батареи в Windows 10. В этом примере пользователь уведомляет пользователя и запускает приложение Параметры для параметров экономии батареи. Пользователь dontAskAgainSetting позволяет пользователю подавлять сообщение, если они не хотят получать уведомления снова.

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.System;
using Windows.System.Power;
...
...
async public void CheckForEnergySaving()
{
   //Get reminder preference from LocalSettings
   bool dontAskAgain;
   var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
   object dontAskSetting = localSettings.Values["dontAskAgainSetting"];
   if (dontAskSetting == null)
   {  // Setting does not exist
      dontAskAgain = false;
   }
   else
   {  // Retrieve setting value
      dontAskAgain = Convert.ToBoolean(dontAskSetting);
   }
   
   // Check if battery saver is on and that it's okay to raise dialog
   if ((PowerManager.EnergySaverStatus == EnergySaverStatus.On)
         && (dontAskAgain == false))
   {
      // Check dialog results
      ContentDialogResult dialogResult = await saveEnergyDialog.ShowAsync();
      if (dialogResult == ContentDialogResult.Primary)
      {
         // Launch battery saver settings (settings are available only when a battery is present)
         await Launcher.LaunchUriAsync(new Uri("ms-settings:batterysaver-settings"));
      }

      // Save reminder preference
      if (dontAskAgainBox.IsChecked == true)
      {  // Don't raise dialog again
         localSettings.Values["dontAskAgainSetting"] = "true";
      }
   }
}
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.System.Power.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Navigation.h>
using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::System;
using namespace winrt::Windows::System::Power;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Navigation;
...
winrt::fire_and_forget CheckForEnergySaving()
{
    // Get reminder preference from LocalSettings.
    bool dontAskAgain{ false };
    auto localSettings = ApplicationData::Current().LocalSettings();
    IInspectable dontAskSetting = localSettings.Values().Lookup(L"dontAskAgainSetting");
    if (!dontAskSetting)
    {
        // Setting doesn't exist.
        dontAskAgain = false;
    }
    else
    {
        // Retrieve setting value
        dontAskAgain = winrt::unbox_value<bool>(dontAskSetting);
    }

    // Check whether battery saver is on, and whether it's okay to raise dialog.
    if ((PowerManager::EnergySaverStatus() == EnergySaverStatus::On) && (!dontAskAgain))
    {
        // Check dialog results.
        ContentDialogResult dialogResult = co_await saveEnergyDialog().ShowAsync();
        if (dialogResult == ContentDialogResult::Primary)
        {
            // Launch battery saver settings
            // (settings are available only when a battery is present).
            co_await Launcher::LaunchUriAsync(Uri(L"ms-settings:batterysaver-settings"));
        }

        // Save reminder preference.
        if (dontAskAgainBox().IsChecked())
        {
            // Don't raise the dialog again.
            localSettings.Values().Insert(L"dontAskAgainSetting", winrt::box_value(true));
        }
    }
}

В этом примере используется XAML для ContentDialog.

<ContentDialog x:Name="saveEnergyDialog"
               PrimaryButtonText="Open battery saver settings"
               SecondaryButtonText="Ignore"
               Title="Battery saver is on."> 
   <StackPanel>
      <TextBlock TextWrapping="WrapWholeWords">
         <LineBreak/><Run>Battery saver is on and you may 
          not receive push notifications.</Run><LineBreak/>
         <LineBreak/><Run>You can choose to allow this app to work normally
         while in battery saver, including receiving push notifications.</Run>
         <LineBreak/>
      </TextBlock>
      <CheckBox x:Name="dontAskAgainBox" Content="OK, got it."/>
   </StackPanel>
</ContentDialog>