Поделиться через


Обзор служб 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 для push-уведомлений

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

Прежде чем отправлять уведомления с помощью 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 канала для подделки 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 для проверки подлинности облачной службы

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

Note

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

 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 для отправки уведомления

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

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

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

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

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

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

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

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

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

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

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

Tip

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

Ниже приведен пример того, как проверить, включена ли экономия батареи в 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 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>