Windows Phoneによるタイル通知の送受信

2011年9月16日(金)
PROJECT KySS

ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbをダブルクリックして、リスト5のコードを記述します。

ロジックコードを記述する

リスト5 (MainWindow.xaml.vb)

Option Strict On
Imports System.Xml.Linq
Imports System.Net
Imports System.IO
Imports System.Text

ImageInfoクラス内に「画像名」という文字列型のプロパティを定義しておきます。
Public Class ImageInfo
  Property 画像名 As String
End Class

Class MainWindow

ImageNameとgetUriというメンバ変数を宣言します。
  Dim ImageName As String = String.Empty
  Dim getUri As String = String.Empty

メインウィンドウが読み込まれた時の処理

新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。WebClientクラスは、データの送受信用のメソッドを提供するクラスです。
String またはUriとして指定したリソースをダウンロードする、DownloadStringAsyncメソッドで、サーバー上のchannelUri.txtをダウンロードします。
AddHandlerメソッドで、非同期のリソース ダウンロード操作の完了時に発生する、DwonloadStringCompletedイベントに、イベントハンドラを追加します。メンバ変数getUriにダウンロードした結果を格納します。チャネルURIが格納されます。
XElement.LoadメソッドでXML文書ファイル(ImageInfo.xml)を読み込みます。
ImageInfoクラスの新しいリストであるmyImageInfoオブジェクトを作成します。
<画像名>要素のコレクション内を変数resultで反復処理しながら、ImageInfoクラスの「画像名」プロパティにImage/フォルダを連結した<画像名>要素の値を指定し、AddメソッドでmyImageInfoオブジェクトに追加していきます。ListBoxのItemsSourceプロパティにmyImageInfoオブジェクトを指定します。これで、ListBoxに桜の画像が表示されます。
  Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    
    Dim myWebClient As New WebClient
 
    AddHandler myWebClient.DownloadStringCompleted, Sub(resultSender As Object, resultArgs As DownloadStringCompletedEventArgs)
                                                    If resultArgs.Error Is Nothing = False Then
                                                      MessageBox.Show("Channelファイルが見つかりません")
                                                      Exit Sub
                                                    Else
                                                      getUri = resultArgs.Result
                                                    End If
                                                End Sub
    myWebClient.DownloadStringAsync(New Uri("http://2008r2.projectkyss.net/TileNotification_NET/SaveData/channelUri.txt", UriKind.Absolute))
 
    Dim xmldoc As XElement = XElement.Load("ImageInfo.xml")
    Dim myImageInfo As New List(Of ImageInfo)
    For Each result In From c In xmldoc.Descendants("画像名") Select c
      myImageInfo.Add(New ImageInfo With {.画像名 = "Image/" & result.Value})
    Next
    ListBox1.ItemsSource = myImageInfo
  End Sub

ListBoxから桜の画像が選択された時の処理

ListBoxより選択された項目を、ImageInfoクラスにキャストして、「画像名」プロパティの値を取得します。パスを除いた画像ファイル名だけを取得して、メンバ変数ImageNameに格納しておきます。
  Private Sub ListBox1_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles ListBox1.SelectionChanged
    Dim selectImageName As String = String.Empty
    selectImageName = DirectCast(ListBox1.SelectedItem, ImageInfo).画像名
    Dim imageLen As Integer = Len(selectImageName) - 6
    ImageName = Right(selectImageName, imageLen)
  End Sub

[タイルに通知を送る]ボタンがクリックされた時の処理

チャネルURIがきちんと取得されている場合の処理です。
HttpWebRequestクラス型のsendNotificationInfoオブジェクト変数を宣言し、WebRequest.Createメソッドで、指定したURI(getUri) で新しいWebRequest のインスタンスを初期化し、DirectCastで、HttpWebRequestクラスにキャストします。HttpWebRequestクラスは、URIへの要求を行うWebRequestクラスの 、HTTP 固有の実装を提供するクラスです。
HttpWebRequestクラスのMethodプロパティに「POST」を指定します。
画像が選択されていなかった場合は警告メッセージを表示します。
変数myCountにcountTextBoxの値を、myTitle変数にtitleTextBoxの値を、myBackTitle変数にbackContentTextBoxの値を格納します。
Visual Basicの埋め込み式を用いて、XML 要素リテラルでxmlData要素を作成しています。埋め込み式の構文は<%= expression %>で、ASP.NET で使用される構文と同じです。
<wp:BackgroundImage>要素の値には、ImageName変数の値を埋め込みます。<wp:Count>要素の値には、myCount変数の値を埋め込みます。<wp:Title>要素の値には、myTitle変数の値を埋め込みます。<wp:BackContent>要素の値には、myBackTitleの値を埋め込みます。
XElement.ParseメソッドでxmlDataの内容を文字列として読み込みます。
送信する通知のデータ本体を設定します。読み込んだXMLデータを、Encoding.UTF8.GetBytesメソッドでUTF8のバイトシーケンスにエンコードし、Byte型のnotificationMessage変数に格納します。
HttpRequestクラスのContentlengthにUTF8のバイトシーケンスにエンコードしたバイト数を指定します。ContentTypeにはtext/xml、HeadersにはAddメソッドで、「"X-WindowsPhone-Target", "token"」と「"X-NotificationClass", "1"」を追加します。X-NotificationClassヘッダには、いつデバイスに通知するかを設定できます。”1”は「プッシュ通知サービスによって、すぐにメッセージを配信」する場合に指定します。”11”を指定すると「450 秒以内に、プッシュ通知サービスによってメッセージを配信」になり、”21”を指定すると「900 秒以内に、プッシュ通知サービスによってメッセージを配信」の意味になります。
  要求データを書き込むために使用する Stream オブジェクトmyStreamを宣言します。 StreamクラスのWriteメソッドでByte型のnotificationMessageを書き込みます。Writeメソッドの書式は下記の通りです。

Write(バイト配列,バイトのコピーを開始する位置でインデックスは0から,書き込むバイト数)

Closeメソッドで、Streamを閉じます。これで、Windows PhoneのタイルのUIが変更されます。
 Private Sub Button1_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
    Try
      If getUri <> String.Empty Then
        Dim sendNotificationInfo As HttpWebRequest = DirectCast(WebRequest.Create(getUri), HttpWebRequest)
        sendNotificationInfo.Method = "POST"
 
        If ImageName = String.Empty Then
          MessageBox.Show("画像を選択してください。")
          Exit Sub
        Else
          Dim myCount As String = countTextBox.Text
          Dim myTitle As String = titleTextBox.Text
          Dim myBackTitle As String = backContentTextBox.Text
          Dim xmlData As XDocument = <?xml version="1.0" encoding="utf-8"?>
                                     <wp:Notification xmlns:wp="WPNotification">
                                       <wp:Tile>
                                         <wp:BackgroundImage><%= ImageName %></wp:BackgroundImage>
                                         <wp:Count><%= myCount %></wp:Count>
                                         <wp:Title><%= myTitle %></wp:Title>
                                         <wp:BackContent><%= myBackTitle %></wp:BackContent>
                                       </wp:Tile>
                                     </wp:Notification>
 
          Dim xmldoc As XElement = XElement.Parse(xmlData.ToString)
          Dim notificationMessage As Byte() = Encoding.UTF8.GetBytes(xmldoc.ToString)
          With sendNotificationInfo
            .ContentLength = notificationMessage.Length
            .ContentType = "text/xml"
            .Headers.Add("X-WindowsPhone-Target", "token")
            .Headers.Add("X-NotificationClass", "1")
          End With
 
          Dim myStream As Stream = sendNotificationInfo.GetRequestStream 
          myStream.Write(notificationMessage, 0, notificationMessage.Length)
          myStream.Close()
        End If
      End If
    Catch ex As Exception
      MessageBox.Show(ex.Message)
    End Try
  End Sub
End Class

筆者は先日Windows Phone OS 7.5搭載のIS12Tを購入しました。今回のプログラムを早速実機(IS12T)にデプロイして動かしてみました。実機で動作させるためにはAPP HUBへの登録と実機のロックを外す必要がありますが、この件に関しては、また別な機会で解説したいと思います。

今回のプログラムを実機(IS12T)で動作させると図6のようになります。

図6:今回のプログラムを実機(IS12T)で動作させた(クリックで拡大)
  • 「Windows Phoneによるタイル通知の送受信」サンプルプログラム

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています