English version

Push Notifications в Windows Phone 7 (toast)

Рассматривая возможности Windows Phone 7 нельзя не обратить внимания на механизм Push Notification, которого не было в предыдущих версиях Windows Phone. Этот механизм сам по себе очень удобный для разработчиков и пользователей и позволяет асинхронно уведомлять пользователя о происходящих событиях. Например, сервис из облака может сообщить пользователю о том, что произошло какое-то событие, на которое нужно как-то отреагировать. Давайте разберемся как устроен этот механизм.

В структуре Push Notifications существует специальный сервис в облаке (размещенный за счет мощностей Microsoft), который делает возможность работы уведомлений. Когда устройство хочет получать уведомления от обращается к этому сервису и устанавливает с ним постоянное соединение. В ответ на это сервис выдает этому устройству уникальный URI, используя который можно отправить по протоколу HTTP некоторое сообщение. Это сообщение получает тот самый сервис в облаке и пересылает его соответствующему устройству. Логично, что для каждого устройства и приложения этот URI будет уникальный. Таким образом, работу уведомлений в Windows Phone 7 можно описать так:

  1. Устройство устанавливает соединение с сервером Microsoft и получает уникальный HTTP-адрес;
  2. Устройство передает этот HTTP-адрес тому, кто будет уведомлять устройство о чем-либо;
  3. Когда необходимо уведомить устройство о чем-либо, приложение, которому был передан HTTP-адрес отправляет специальное HTTP-сообщение на этот адрес;
  4. Сервис Microsoft получает это сообщение и по возможности доставляет его на устройство. Если доставить сообщение на устройство не удалось, то отправитель получит соответствующее сообщение.

Схематически этот алгоритм можно изобразить следующим образом.

Push Notifications в Windows Phone 7 (toast)

Существуют три разных вида уведомлений для Windows Phone 7:

Toast Notifications

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

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

<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="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>

Теперь при старте приложения следует соединиться с сервисом уведомлений и получить адрес для отправки уведомлений. Для этих целей следует подключить сборку Microsoft.Phone.Notification и использовать объект HttpNotificationChannel. Если мы еще не обращались к сервису уведомлений, то необходимо использовать метод Open() и установить соединение; если ранее мы уже обращались к сервису, то нужно просто заново соединиться с сервисом, используя метод Find(). При установлении соединения мы должны указать уникальное имя канала и/или сервиса. Эти параметры задаются в конструкторе объекта HttpNotificationChannel.

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

После запуска приложения выведем текущий адрес для уведомлений на экран, а также в консоль отладки (чтобы этот адрес можно было скопировать в буфер обмена). Таким образом мы получим небольшой фрагмент кода для приложения Windows Phone 7.

public partial class MainPage : PhoneApplicationPage
{
    private HttpNotificationChannel notifications;
    private const string notificationServiceName = "Some test";

    public MainPage()
    {
        InitializeComponent();

        SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;

        InitializePushChannel();
    }

    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);
            }
        }
    }

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

    private void notifications_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
    {
        ShowUri(e.ChannelUri);
    }
}

На этом создание приложения для устройства завершено. Теперь нам необходимо отправить специальное HTTP-сообщение по адресу для уведомлений. Для этих целей можно использовать различные сторонние утилиты, например, Fiddler. Однако, давайте пройдем путь до конца и создадим приложение, которое будет отправлять соответствующие уведомления по указанному адресу.

Для того, чтобы отправить Toast-уведомление следует использовать следующий формат сообщения:

X-WindowsPhone-Target: toast

<?xml version=""1.0"" encoding=""utf-8""?>
<wp:PushNotification xmlns:wp=""WindowsPhonePushNotification"">
    <wp:Toast>
        <wp:Text1>Header</wp:Text1>
        <wp:Text2>Text</wp:Text2>
    </wp:Toast>
</wp:PushNotification>

В данном случае Header и Text – это те значения, которые пользователь увидит у себя на экране. Кроме того, HTTP-сообщение должно иметь заголовок X-NotificationClass, которое отражает важность доставляемого сообщения. Более подробно о формате сообщений и классе важности сообщений можно почитать здесь и здесь.

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

Теперь, все, что осталось сделать – это отправить соответствующий HTTP-запрос по указанному адресу и обработать результат. Сделаем небольшое консольное приложение в которое поместим следующий код.

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

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

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

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

        var message = "X-WindowsPhone-Target: toast" + Environment.NewLine + Environment.NewLine +
            @"<?xml version=""1.0"" encoding=""utf-8""?>
                <wp:PushNotification xmlns:wp=""WindowsPhonePushNotification"">
                    <wp:Toast>
                        <wp:Text1>{0}</wp:Text1>
                        <wp:Text2>{1}</wp:Text2>
                    </wp:Toast>
                </wp:PushNotification>";



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

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

Push Notifications в Windows Phone 7 (toast)

Если теперь взглянуть на экран эмулятора Windows Phone 7, то можно увидеть, что там появилось соответствующее уведомление.

Push Notifications в Windows Phone 7 (toast)

Обратите внимание, что вместе с сообщением отображается некий значок. Это – значок приложения, который можно легко изменить.

Как видно, создать свое приложение, использующее уведомления очень просто. Ну а в следующий раз я расскажу о том, как использовать Raw Notifications.

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

  1. Исходный код приложения
Push Notifications в Windows Phone 7 (raw) ← → Меню и Application Bar для приложений Windows Phone 7

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

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

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