Разработка под Windows Phone: Push Notification

Возможность Push оповещений, т.е. получения информации об изменении какого-то внешнего ресурса, без необходимости его постоянно опрашивать (Poll). Этот механизм реализован через специальный внешний сервис – Microsoft Push Notification Service, который и отвечает за отсылку Push оповещения на устройство.

Схематично работа с сервисом Microsoft Push Notification Service представлена на следующем рисунке.

img_6_15_2

Приложение, которое хочет использовать Push оповещения, запрашивает URI у клиента Push сервиса оповещений (1), клиент Push сервиса взаимодействует с Microsoft Push Notification Service (MSPN), получает от него URI (2) и отдаёт его приложению (3). Приложение передаёт этот URI своему сервису, который будет формировать сообщения приложению и отсылать их методом POST в сервис MSPN (5) по указанному URI. Когда сервис MSPN получает сообщение, он запускает процедуру доставки его на устройство (6).

Обратите внимание, что сервис MSPN не оповещает сервис, формирующий сообщения о том, когда сообщение получено устройством.

Прежде чем перейти к типам оповещений, перечислим несколько базовых технических ограничений:

· на одно приложение – один канал Push оповещений;

· не более 30 каналов Push оповещений на устройство;

· максимальный размер оповещения: 1 Кб для заголовка и 3 Кб на содержимое.

Всего доступно три типа Push оповещений:

  1. Toast;
  2. Tile;
  3. Raw.

Приложение может зарегистрировать на получение Toast оповещение. Тогда, если приложение запущено, и приходит Toast оповещение, оно не отображается в верхней части экрана. Если приложение не зарегистрировано на получение Toast оповещения или не запущено, то Toast оповещение, отображается в верхней части экрана, сообщая пользователю о том, что что-то требует его внимания. При нажатии на оповещение запускается приложение. Разработчику доступны Deep Toast оповещения, когда при запуске открывается не стартовая страница приложения, а определённая и с определёнными параметрами. Пример Toast оповещения – оповещение о приходе SMS.

Основное назначение Tile оповещения – обновление тайлов приложения, закреплённых на стартовой панели. Приложение не получает Tile оповещение.

Оповещение типа Raw, позволяет отправить сообщение работающему приложению. Если приложение на момент получения не запущено, сообщение не будет отправлено на устройство.

Перейдём к практическому знакомству с возможностями Push Notification. Создадим новое приложение на базе стандартного шаблона Windows Phone Application и назовём приложение PushNotificationExample.

Как понятно, необходим какой-то сервис, чтобы посылать сообщения по полученному URI в MPNS. Мы не будем останавливаться здесь на этом подробно, а просто воспользуемся примерами тестовых ASP.NET приложений:

В примере к этому разделу все три страницы включены в один проект и объединены в одно решение с проектом PushNotificationExample для Windows Phone.

Вернёмся к приложению для Windows Phone. У него будет очень простой функционал. Приложение будет регистрировать канал и на нём ожидать всех типов оповещений: Toast, Tile и Raw.

Сначала слегка изменим и дополним дизайн MainPage.xaml:

 <!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
      <TextBlock x:Name="ApplicationTitle" Text="PUSH NOTIFICATION"
                 Style='{StaticResource PhoneTextNormalStyle}'/>
      <TextBlock x:Name="PageTitle" Text="настройки"
                 Margin="9,-7,0,0" Style='{StaticResource PhoneTextTitle1Style}'/>
</StackPanel>

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
   <StackPanel>
       <Button Name="SetPushNotification" Content="установка оповещений" />
    </StackPanel>
</Grid>

Двойным щелчком по кнопке «установка оповещений» в коде дизайнера создадим и перейдём в обработчик события Click кнопки.

Добавим код, который ищет канал с имеем «MyChannel», если не находит, то создаёт, после чего регистрируется на обработку событий Toast и Raw (Tile сообщение до приложения не доходит, оно напрямую меняет тайл).

 private void SetPushNotification_Click(object sender, RoutedEventArgs e)
{
 
      HttpNotificationChannel myChannel;
      bool isNewChannel = false;
      string myChannelName = "MyChannel";
 
      myChannel = HttpNotificationChannel.Find(myChannelName);
 
      if (myChannel == null)
      {
 
          myChannel = new HttpNotificationChannel(myChannelName);
          isNewChannel = true;
      }
 
      //получаем URI и его изменения
      myChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(myToastChannel_ChannelUriUpdated);
 
      //обрабатываем ошибки
      myChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(myToastChannel_ErrorOccurred);
 
      //реагируем на получение Toast оповещения при запущеном приложении
      myChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(myToastChannel_ShellToastNotificationReceived);
 
      //реагируем на получение Raw оповещения при запущеном приложении
      myChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(myToastChannel_HttpNotificationReceived);
 
      if (isNewChannel)
           myChannel.Open();
 
      // говорим о том, что у нас будут toast оповещения
      if (!myChannel.IsShellToastBound)
           myChannel.BindToShellToast();
 
      // говорим о том, что у нас будут tile оповещения
      if (!myChannel.IsShellTileBound)
             myChannel.BindToShellTile();
 
       // если канал был раньше – посылаем URI сервису
       if (!isNewChannel)
             SendURIToService(myChannel.ChannelUri);

}

Добавим обработчики событий ошбок и получения/изменения URI

 void myToastChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
    // здесь мы должны были бы обработать ошибку 
    // здесь просто выводим, для использования в тестировании
    Dispatcher.BeginInvoke(() =>
    {
        System.Diagnostics.Debug.WriteLine(e.Message);
        MessageBox.Show(String.Format("Error: {0}", e.Message));
     });
}
 
void myToastChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
   // здесь мы должны были бы отослать URI нашему сервису
   // просто выводим, для использования в тестировании
   // из-за взаимодействия c UI - используем Dispatcher
    Dispatcher.BeginInvoke(() => SendURIToService(e.ChannelUri));
}

В нашем случае, функция SendURIToService() просто отображает сообщение в UI, поэтому и необходимо обернуть её в диспатчер:

 void SendURIToService(Uri channelURI)
{
   // здесь мы должны были бы отослать URI нашему сервису
   // просто выводим, для использования в тестировании
   System.Diagnostics.Debug.WriteLine(channelURI.ToString());
   MessageBox.Show(String.Format("Uri: {0}", channelURI.ToString()));
}

В завершении, добавим обработчик Toast и Raw оповещений, который будут работать при запущенном приложении:

 void myToastChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{

   // здесь мы должны были бы обработать сообщение
   // здесь просто выводим, для использования в тестировании
   StringBuilder sb = new StringBuilder();
 
   foreach (string key in e.Collection.Keys)
   {
       sb.AppendFormat("{0}:{1}\n", key, e.Collection[key]);
   }
 
   string result = sb.ToString();
 
   Dispatcher.BeginInvoke(() =>
   {
      System.Diagnostics.Debug.WriteLine(result);
      MessageBox.Show(result);
   }); 
}
 
void myToastChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
{
 
   //добавьте свой обработчик Raw сообщения, который будет его разбирать
   Dispatcher.BeginInvoke(() =>
   {
      System.Diagnostics.Debug.WriteLine("Получено Raw сообщение.");
      MessageBox.Show("Получено Raw сообщение");
   });
}

Запустите решение (F5), откройте страницу ASP.NET проекта в браузере. В окне приложения, нажмите на кнопку «установка оповещений» и дождитесь отображения URI в окне вывода отладочной информации:

img_6_16

Закройте диалоговое окно приложения. Скопируйте URI из окна вывода отладочной информации и перейдите на страницу Toast оповещения, введите скопированный URI, введите Title и Subtitle и, нажав на кнопку, отошлите сообщение. Поскольку приложение запущено, оно самостоятельно обработает сообщение и выведет диалоговое окно:

img_6_17

Toast сообщение не отобразится.

Закройте приложение, нажав кнопку Back (отладка завершится), перейдите к веб-приложению и ещё раз отправьте Toast сообщение. Теперь оно отобразится в интерфейсе пользователя.

img_6_18

Перейдите к списку приложений и закрепите приложение PushNotificationExample в стартовую панель (pin to start).

img_6_19

Перейдите к веб-приложению на страницу отправки Tile сообщения и отправьте Tile сообщение, указав Front Title и Count (не забудьте указать URI). Обратите внимание, как изменился тайл приложения.

img_6_20

В качестве самостоятельно работы, запустите приложение и проверьте, что оно получает Raw сообщения.

Добавьте в приложения картинки и сформируйте Tile сообщение, чтобы они использовались в обновлённом тайле.