Статьи

WP7 Push-уведомления, часть 2

До сих пор мы рассматривали важность уведомлений на платформе Windows Phone вместе с различными типами уведомлений , доступных для вашего приложения. В этом посте мы рассмотрим настройку вашего приложения для получения уведомлений и способы отправки уведомлений.

Первым шагом в настройке приложения для получения уведомлений является регистрация в службе push-уведомлений Microsoft. Это делается путем создания экземпляра класса HttpNotificationChannel и вызова метода Open . Метод Open — это асинхронный метод, который устанавливает канал связи между службой push-уведомлений и вашим приложением, запущенным на этом конкретном устройстве. После открытия канала Channel Uri (который можно считать уникальным идентификатором канала) возвращается приложению через экземпляр HttpNotificationChannel . Событие HttpNotificationChannel экземпляре HttpNotificationChannel , позволяя приложению определить, когда был настроен канал.

Следующий код иллюстрирует создание HttpNotificationChannel, подключение события ChannelUriUpdated и затем открытие канала. Метод Open будет возвращен немедленно, ChannelUriUpdated событие ChannelUriUpdated будет ChannelUriUpdated вскоре после настройки канала. Обратите внимание, что ChannelName — это произвольное имя, которое вы назначаете каналу для вашего приложения.

 private const string ChannelName = "MyApplicationChannel"; public HttpNotificationChannel Channel { get; set; } public bool ChannelIsActive { get; set; } private void EstablishNotificationChannel() { Channel = new HttpNotificationChannel(ChannelName); Channel.ChannelUriUpdated += HttpChannelChannelUriUpdated; Channel.Open(); } private void HttpChannelChannelUriUpdated(object sender, NotificationChannelUriEventArgs e) { UpdateChannelIsActive(); } private void UpdateChannelIsActive() { ChannelIsActive = Channel != null && Channel.ChannelUri != null && !string.IsNullOrEmpty(Channel.ChannelUri.OriginalString); } 

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

 private void EstablishNotificationChannel() { Channel = HttpNotificationChannel.Find(ChannelName); if (Channel == null) { Channel = new HttpNotificationChannel(ChannelName); Channel.ChannelUriUpdated += HttpChannelChannelUriUpdated; Channel.Open(); } else { Channel.ChannelUriUpdated += HttpChannelChannelUriUpdated; } UpdateChannelIsActive(); } 

Следует отметить, что даже если HttpNotificationChannel существует, вы все равно должны ChannelUriUpdated событие ChannelUriUpdated поскольку существуют сценарии, когда будет HttpNotificationChannel экземпляр HttpNotificationChannel , но канал не имел возможности инициализироваться. В этих случаях после настройки канала будет ChannelUriUpdated событие ChannelUriUpdated .

Пока что все, что мы сделали, это установили канал, по которому можно получать уведомления. Тем не менее, мы не сказали приложению или устройству, что делать при получении уведомления. Давайте пройдемся по каждому типу уведомлений по очереди.

Сырое уведомление

Когда канал уже установлен, вам больше ничего не нужно делать, чтобы настроить канал для получения уведомлений в приложении. Однако для обработки полученного уведомления вам нужно добавить обработчик события в событие HttpNotificationChannel в HttpNotificationChannel . Рисунок 4 иллюстрирует обработчик события для этого события; Свойство Body объекта Notification — это поток, из которого ваше приложение может прочитать, представляющий необработанные байты, отправленные через необработанное уведомление.

Push-уведомления Рисунок 1

фигура 1

Отправка любого типа уведомления — это вопрос выполнения HTTP-операции POST в ChannelUri экземпляра приложения. Вы должны установить некоторые дополнительные заголовки, а полезные данные должны быть соответствующим образом отформатированы в зависимости от типа отправляемого уведомления. Для необработанного уведомления полезная нагрузка не структурирована.

Следующий код устанавливает новый веб-запрос к предоставленному channelUri , устанавливает соответствующие заголовки, открывает поток запросов, записывает notificationMessage и затем завершает запрос. Этот код также иллюстрирует, как можно проанализировать ответ для извлечения информации о состоянии об уведомлении, канале и подключенном состоянии устройства.

 private static Guid SendNotification(byte[] notificationMessage, Uri channelUri, int notificationType, string targetHeader = null) { var request = (HttpWebRequest)WebRequest.Create(channelUri); request.Method = "POST"; request.Headers = new WebHeaderCollection(); var messageId = Guid.NewGuid(); request.Headers["X-MessageID"] = messageId.ToString(); request.Headers["X-NotificationClass"] = notificationType.ToString(); if (!string.IsNullOrEmpty(targetHeader)) { request.ContentType = "text/XML"; request.Headers["X-WindowsPhone-Target"] = targetHeader; } request.BeginGetRequestStream((result) => { var req = result.AsyncState as HttpWebRequest; using (var requestStream = req.EndGetRequestStream(result)) { requestStream.Write(notificationMessage, 0, notificationMessage.Length); } req.BeginGetResponse((responseResult) => { var responseRequest = result.AsyncState as HttpWebRequest; using (var response = responseRequest.EndGetResponse(responseResult)) { string notificationStatus = response.Headers["X-NotificationStatus"]; string notificationChannelStatus = response.Headers["X-SubscriptionStatus"]; string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"]; } }, req); }, request); return messageId; } 

Теперь все, что вам нужно сделать, это вызвать метод SendNotification с соответствующими параметрами. Для необработанного уведомления вы должны сделать следующий звонок. 3 указывает, что тип уведомления является необработанным уведомлением, которое должно быть отправлено немедленно.

 private void SendRawClick(object sender, RoutedEventArgs e) { var msg = Encoding.UTF8.GetBytes("Hello World!"); SendNotification(msg, Channel.ChannelUri, 3); } 

Обратите внимание, что в случае необработанного уведомления вам не нужно указывать свойство targetHeader поскольку оно относится только к плиткам и тост-уведомлениям.

Тост Уведомление

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

 Channel = new HttpNotificationChannel(ChannelName); Channel.ChannelUriUpdated += HttpChannelChannelUriUpdated; Channel.Open(); Channel.BindToShellToast(); 

Когда пользователь находится в вашем приложении и в ваше приложение отправляется тост-сообщение, а не обычный тост-интерфейс, ваше приложение будет перехватывать это сообщение, вызывая событие HttpNotificationChannel экземпляре HttpNotificationChannel .

 Channel.HttpNotificationReceived += HttpChannelHttpNotificationReceived; Channel.ShellToastNotificationReceived += HttpChannelShellToastNotificationReceived; 

В соответствующем обработчике событий вы можете проанализировать коллекцию возвращаемых строк. Тостовые уведомления состоят из двух строк с ключевыми значениями «text1» и «text2».

 private void HttpChannelShellToastNotificationReceived(object sender, NotificationEventArgs e) { var sb = new StringBuilder(); foreach (var kvp in e.Collection) { sb.AppendLine(string.Format("Key:{0} Value:{1}", kvp.Key, kvp.Value)); } this.Dispatcher.BeginInvoke(() => { MessageBox.Show(sb.ToString()); }); } 

Наконец, для отправки всплывающего уведомления вам просто нужно сгенерировать правильно сформированный XML и преобразовать его в байтовый массив, который становится полезной нагрузкой уведомления.

 private void SendToastClick(object sender, RoutedEventArgs e) { var messageTemplate = "<?XML version="1.0" encoding="utf-8"?>" + "<wp:Notification XMLns:wp="WPNotification">" + "<wp:Toast>" + "<wp:Text1>{0}</wp:Text1>" + "<wp:Text2>{1}</wp:Text2>" + "</wp:Toast>" + "</wp:Notification>"; var message = string.Format(messageTemplate, "Hello", "World!"); byte[] msg = Encoding.UTF8.GetBytes(message); SendNotification(msg, Channel.ChannelUri, 2,"toast"); } 

В этом случае значение 2, указанное в методе SendNotification указывает на немедленное уведомление о тосте. Обратите внимание, что вам также необходимо указать параметр targetHeader для «toast».

Плитка Уведомление

Как и в случае с всплывающими уведомлениями, для того, чтобы устройство обрабатывало уведомление о плитке, пока приложение не запущено, необходимо сообщить об этом операционной системе. Это делается с BindToShellTile метода BindToShellTile . Обратите внимание, что, поскольку вы можете обновить Live Tile фоновым изображением с удаленного сервера, метод BindToShellTile может принять коллекцию доменов в качестве параметра. В фоновом уведомлении могут быть указаны только фоновые изображения из этих доменов (или локальных плиток, поставляемых с приложением).

 Channel = new HttpNotificationChannel(ChannelName); Channel.ChannelUriUpdated += HttpChannelChannelUriUpdated; Channel.Open(); var allowedDomains = new Collection<Uri>(); allowedDomains.Add(new Uri("Http://www.builttoroam.com")); Channel.BindToShellTile(allowedDomains); 

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

 private void SendTileClick(object sender, RoutedEventArgs e) { var messageTemplate = "<?XML version="1.0" encoding="utf-8"?>" + "<wp:Notification XMLns:wp="WPNotification">" + "<wp:Tile>" + "<wp:BackgroundImage>{0}</wp:BackgroundImage>" + "<wp:Count>{1}</wp:Count>" + "<wp:Title>{2}</wp:Title>" + "</wp:Tile> " + "</wp:Notification>"; var message = string.Format(messageTemplate, "Background2.jpg", 5, "New Title"); byte[] msg = Encoding.UTF8.GetBytes(message); SendNotification(msg, Channel.ChannelUri, 1, "token"); } 

Обратите внимание, что «1» указывает, что уведомление плитки должно быть отправлено немедленно и что targetHeader должен быть «токеном» (а не «плиткой», как вы ожидали). Это конкретное обновление плитки ссылается на другое изображение, Background2.jpg, которое упаковано как Контент в файле XAP приложения, значок 5 и новый заголовок, который будет отображаться, как показано на рисунке 2.

Push-уведомления Рисунок 2

фигура 2

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