English version

Push Notifications в Windows Phone 7 (raw)

Я уже рассказывал о том, что представляют собой уведомления в Windows Phone 7. Используя этот механизм можно доставлять уведомление из сервиса в облаке непосредственно на мобильное устройство.

Я не буду рассматривать устройство механизма уведомлений в целом (ознакомиться с ним можно здесь), повторю только отдельные типы уведомлений:

На этот раз давайте поговорим о Raw Notifications.

Raw Notifications

Raw Notifications – это наиболее гибкий тип уведомлений. Обрабатывать данный тип уведомлений можно по своему усмотрению, используя нужный для приложения алгоритм. Если в случае с Toast Notifications и Tile Notifications мы должны соблюдать определенный формат и тип передаваемых данных (для Toast – строка, для Tile – адрес до изображения). то в случае с Raw Notifications мы можем передавать абсолютно любые данные, которые нам необходимы.

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

private HttpNotificationChannel notifications;
private const string notificationServiceName = "Some test";

private void InitializePushChannel()
{
    if (notifications != null)
    {
        ShowUri(notifications.ChannelUri);
    }
    else
    {
        try
        {
            notifications = new HttpNotificationChannel(Application.Current.ToString(), notificationServiceName);
            notifications.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(notifications_ChannelUriUpdated);
            notifications.Open();
            ShowUri(notifications.ChannelUri);

            notifications.BindToShellNotification();
        }
        catch (NotificationChannelExistsException)
        {
            notifications = HttpNotificationChannel.Find(Application.Current.ToString());
            notifications.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(notifications_ChannelUriUpdated);
            ShowUri(notifications.ChannelUri);
        }
    }
}

Как видно, для работы с механизмом уведомлений используется все тот же объект HttpNotificationChannel. Аналогичным образом следует обрабатывать ситуацию, когда сервис уже был зарегистрирован (в этом случае следует использовать метод Find). Также следует обрабатывать событие ChannelUriUpdated на случай, если сервис в облаке решит изменить адрес для отправки уведомлений. Для этого мы создадим специальный обработчик, который в случае изменения адреса будет отображать его пользователю.

private void ShowUri(Uri uri)
{
    if (uri != null)
    {
        Dispatcher.BeginInvoke(() => ChannelUri.Text = uri.ToString());
        Debug.WriteLine(uri.ToString());
    }
}

Для того, чтобы обработать данные, которые были получены с помощью Raw-уведомлений следует подписаться на событие HttpNotificationReceived. Это событие будет срабатывать всякий раз, когда поступает новое Raw-уведомление.

private HttpNotificationChannel notifications;
private const string notificationServiceName = "Some test";

private void InitializePushChannel()
{
    if (notifications != null)
    {
        ShowUri(notifications.ChannelUri);
    }
    else
    {
        try
        {
            notifications = new HttpNotificationChannel(Application.Current.ToString(), notificationServiceName);
            notifications.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(notifications_ChannelUriUpdated);
            notifications.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(notifications_HttpNotificationReceived);
            notifications.Open();
            ShowUri(notifications.ChannelUri);

            notifications.BindToShellNotification();
        }
        catch (NotificationChannelExistsException)
        {
            notifications = HttpNotificationChannel.Find(Application.Current.ToString());
            notifications.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(notifications_ChannelUriUpdated);
            notifications.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(notifications_HttpNotificationReceived);
            ShowUri(notifications.ChannelUri);
        }
    }
}

Теперь создадим обработчик, который будет срабатывать в момент получения уведомлений. Для этого мы уже подписались на событие HttpNotificationReceived. В параметрах обработчика события передается объект HttpNotificationEventArgs, позволяющий получить доступ к телу HTTP-запроса, который был получен от приложения, создавшего уведомление. В простейшем случае давайте отобразим это сообщение пользователю. Тело сообщения доступно как поток (Stream). Для его чтения мы будем использовать объект StreamReader.

void notifications_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
{
    using (var r = new StreamReader(e.Notification.Body))
    {
        var data = r.ReadToEnd();
        Debug.WriteLine(data);
        Dispatcher.BeginInvoke(() => ReceivedData.Text = data);
    }
}

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

<phoneNavigation:PhoneApplicationPage
    x:Class="ToastNotification.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}">

    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.Background>
            <ImageBrush ImageSource="FormBackground.jpg" Stretch="UniformToFill"/>
        </Grid.Background>

        <!--TitleGrid is the name of the application and page title-->
        <Grid x:Name="TitleGrid" Grid.Row="0">
            <TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" Style="{StaticResource PhoneTextPageTitle1Style}"/>
            <TextBlock Text="Notifications" x:Name="textBlockListTitle" Style="{StaticResource PhoneTextPageTitle2Style}"/>
        </Grid>

        <!--ContentGrid is empty. Place new content here-->
        <Grid x:Name="ContentGrid" Grid.Row="1">
            <Border VerticalAlignment="Top" HorizontalAlignment="Center" Margin="20" Padding="20" CornerRadius="5">
                <Border.Background>
                    <SolidColorBrush Color="Black" Opacity="0.2"/>
                </Border.Background>
                <TextBlock Name="ReceivedData"
                           TextWrapping="Wrap"
                           FontSize="30"/>
            </Border>

            <Border VerticalAlignment="Center" HorizontalAlignment="Center" Margin="20" Padding="20" CornerRadius="5">
                <Border.Background>
                    <SolidColorBrush Color="Black" Opacity="0.2"/>
                </Border.Background>
                <TextBlock Name="ChannelUri"
                           TextWrapping="Wrap"
                           FontSize="30"/>
            </Border>

        </Grid>
    </Grid>

</phoneNavigation:PhoneApplicationPage>

Мобильное приложение готово, теперь, используя полученный URI для отправки уведомлений отправить HTTP-запрос по этому адресу. Для этого как раньше создадим небольшое консольное приложение, способное выполнить эти несложные действия. Для этих целей мы все так же будем использовать объект WebClient. Однако, в отличие от Toast Notifications, при отправке Raw Notifications не нужно соблюдать какой-либо формат сообщения – можно просто записать в тело сообщения те данные, которые необходимо отправить мобильному устройству. Также стоит изменить заголовок “X-NotificationClass” на значение “3”, что будет означать наивысший приоритет отправки для Raw-уведомлений.

При отправке уведомления, в ответ мы также получим два заголовка “X-DeviceConnectionStatus” и “X-NotificationStatus”, которые позволяют определить состояние подключения устройства к сети и статус доставки этого сообщения. Таким образом, код нашего простого приложения будет выглядеть следующим образом.

class Program
{
    private const string Url = @"http://sn1.notify.live.net/throttledthirdparty/01.00/AAFTkavjFpAuT4i1fIKvueDiAgoOs1ADAgAAAAQOMDAwAAAAAAAAAAAAAAA";

    static void Main(string[] args)
    {
        Console.Write("Text: ");
        string text = Console.ReadLine();
        SendToast(Url, text);
        Console.ReadLine();
    }

    static void SendToast(string uri, string text)
    {
        var client = new WebClient();

        client.Headers.Add("Content-Type", "text/html");
        client.Headers.Add("X-NotificationClass", "3");

        var result = client.UploadString(uri, "POST", text);
        Console.WriteLine(result);
        Console.WriteLine("Device status is {0}", client.ResponseHeaders["X-DeviceConnectionStatus"]);
        Console.WriteLine("Notification status is {0}", client.ResponseHeaders["X-NotificationStatus"]);
    }
}

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

Push Notifications в Windows Phone 7 (raw)

Мы создали с вами тривиальное приложение, которое получая строку просто отображает её на экране. Однако, вся мощь Raw Notifications состоит в том, что мы можем определить совершенно любое поведение для обработки уведомлений. Например, давайте изменим приложение так, чтобы при получении названий некоторых цветов оно изменяло цвет букв, отображающих сообщение уведомления.

void notifications_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
{
    using (var r = new StreamReader(e.Notification.Body))
    {
        var data = r.ReadToEnd().Trim('\0');
        Debug.WriteLine(data);

        switch (data)
        {
            case "red":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.Red));
                break;
            case "green":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.Green));
                break;
            case "blue":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.Blue));
                break;
            case "white":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.White));
                break;
            case "black":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.Black));
                break;
            case "yellow":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.Yellow));
                break;
            case "orange":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.Orange));
                break;
            case "gray":
                Dispatcher.BeginInvoke(() => ReceivedData.Foreground = new SolidColorBrush(Colors.Gray));
                break;
            default:
                Dispatcher.BeginInvoke(() => ReceivedData.Text = data);
                break;
        }
    }
}

Теперь, при отправке уведомлений, содержащих имена цветов, цвет текста в приложении будет изменяться.

Push Notifications в Windows Phone 7 (raw)

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

Ссылки по теме

  1. Исходный код приложения
Совместимость приложений Windows Phone Classic и Windows Phone 7 ← → Push Notifications в Windows Phone 7 (toast)

Похожие публикации

Добавить комментарий

Для отображения аватара испольузется Gravatar
Можно форматрировать текст при помощи Markdown