Windows Phoneによるメッセージの受信

2011年11月4日(金)
PROJECT KySS

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

リスト3  (MainWindow.xaml.vb)

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

messageInfoクラス内に「送信日時」、「内容」のプロパティを定義しておきます。
Public Class messageInfo
  Property 送信日時 As String
  Property 内容 As String
End Class

Class MainWindow

XElementクラスのメンバ変数、myDocとreadXmlを宣言しておきます。
  Dim myDoc As XElement
  Dim readXml As XElement

  Dim getUri As String = String.Empty

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

新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。WebClientクラスは、データの送受信用のメソッドを提供するクラスです。
String またはUriとして指定したリソースをダウンロードする、DownloadStringAsyncメソッドで、サーバー上のchannelUri.txtをダウンロードします。Windows Phoneからサーバーに送信されたデータです。
AddHandlerステートメントで、非同期のリソース ダウンロード操作の完了時に発生する、DwonloadStringCompletedイベントに、イベントハンドラを追加します。メンバ変数getUriにダウンロードした結果を格納します。チャネルURIが格納されます。
※サーバーに配置した、ChannelUri_NETの、ASP.NETファイルへのアクセス許可やIISの設定は、各自が行ってください。
  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("サーバーのURI/ChannelUri_NET/SaveData/channelUri.txt", UriKind.Absolute))
    End Sub

[OK]ボタンがクリックされた時の処理

メッセージが何も入力されていない場合は、警告メッセージを表示します。メッセージが入力されている場合は、以下の処理を行います。
新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。WebClientクラスは、データの送受信用のメソッドを提供するクラスです。
String またはUriとして指定したリソースをダウンロードする、DownloadStringAsyncメソッドで、サーバー上のmessageInfo.xmlをダウンロードします。
AddHandlerステートメントで、非同期のリソース ダウンロード操作の完了時に発生する、DwonloadStringCompletedイベントに、イベントハンドラを追加します。XMLファイルが見つからない場合はメッセージを表示して処理を抜けます。
変数myDateTimeに年月日と時間分秒を作成して格納しておきます。
XElement.ParseメソッドでダウンロードしたXMLファイルを文字列として読み込みます。
<情報>要素を生成し、子要素として<送信日時>を生成し、内容テキストにmyDateTime変数の値を指定します。次に、<内容>要素を生成し、内容テキストにTextBoxに入力された値を指定します。生成したXMLデータ(readXml)を読み込んだXML(myDoc)に追加します。
[送信]ボタンの使用を可能にします。
  Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
  If TextBox1.Text = String.Empty Then
          MessageBox.Show("メッセージを入力してください。")
          Button2.IsEnabled = False
          Exit Sub
  Else
          Dim myWebClient As New WebClient
 
          AddHandler myWebClient.DownloadStringCompleted, Sub(resultSender As Object, resultArgs As DownloadStringCompletedEventArgs)
            If resultArgs.Error Is Nothing = False Then
              MessageBox.Show("XMLファイルが見つかりません")
              Exit Sub
            Else
              Dim myYear As Integer = Now.Year
              Dim myMonth As Integer = Now.Month
              Dim myDay As Integer = Now.Day
              Dim myDate As String = myYear & "年" & myMonth & "月" & myDay & "日"
 
              Dim myHour As Integer = Now.Hour
              Dim myMinute As Integer = Now.Minute
              Dim mySecond As Integer = Now.Second
              Dim myTime As String = myHour & "時" & myMinute & "分" & mySecond & "秒"
 
              Dim myDateTime As String = myDate & myTime
              myDoc = XElement.Parse(resultArgs.Result)
  
              readXml = New XElement("情報",
                                  New XElement("送信日時", myDateTime),
                                  New XElement("内容", TextBox1.Text))
                                  myDoc.Add(readXml)
            End If
          End Sub
          
          myWebClient.DownloadStringAsync(New Uri(String.Format("サーバーのURI/Message_NET/SaveData/messageInfo.xml?myTime={0}", DateTime.Now.ToLongTimeString), UriKind.Absolute))
          Button2.IsEnabled = True
  End If
    End Sub

[送信]ボタンが]クリックされた時の処理

メッセージが未入力の場合は警告を表示して処理を抜けます。
変数mySaveDataに[OK]ボタンクリック時に作成されたXMLデータを文字列として格納します。
新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。WebClientクラスは、データの送受信用のメソッドを提供するクラスです。
EncodingプロパティにUTF8を指定し、HeadersのContent-Typeに「text/xml; charset=utf-8」と指定します。
UploadStringAsyncメソッドで、生成したXMLデータ(saveXmlData)をサーバーにアップロードし、サーバー上のDefault.aspxを実行します。アップするサーバーのURIは各自のURIに変更してください。UploadStringAsyncメソッドは、指定したリソースに指定した文字列(この場合、生成したXMLデータ)をアップロードします。
AddHanderステートメントで、非同期の文字列アップロード操作の完了時に発生する、UploadStringCompletedイベントに、イベントハンドラを追加します。イベントハンドラ内では、アップロードに成功した場合は「保存しました」のメッセージを表示します。
※サーバーに配置した、Message_NETのASP.NETファイルのアクセス許可やIISの設定等については、各自が行ってください。
トースト通知をWindows Phoneに送信するToastMessageプロシージャを実行します。
  Private Sub Button2_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles Button2.Click
    If TextBox1.Text = String.Empty Then
      MessageBox.Show("メッセージを入力してください。")
      Button2.IsEnabled = False
      Exit Sub
    Else
      Dim saveXmlData As String
      saveXmlData = myDoc.ToString
      Dim myWebClient As New WebClient
      With myWebClient
        .Encoding = System.Text.Encoding.UTF8
        .Headers("content-type") = "text/xml; charset=utf-8"
      End With
 
      AddHandler myWebClient.UploadStringCompleted, Sub(resultSender As Object, resultArgs As UploadStringCompletedEventArgs)
                             MessageBox.Show("保存しました")
                         End Sub
                         
      myWebClient.UploadStringAsync(New Uri(String.Format("http://2008r2.projectkyss.net/Message_NET/Default.aspx?myTime={0}", DateTime.Now.ToLongTimeString), UriKind.Absolute), saveXmlData)
      TextBox1.Text = String.Empty
 
      ToastMessage()
    End If

トースト通知をWindows Phoneに送信する処理

HttpWebRequestクラス型のsendToastNotificationオブジェクト変数を宣言し、WebRequest.Createメソッドで、指定したURI(getUri) で新しいWebRequest のインスタンスを初期化し、DirectCastで、HttpWebRequestクラスにキャストします。HttpWebRequestクラスは、URIへの要求を行うWebRequestクラスの 、HTTP 固有の実装を提供するクラスです。
HttpWebRequestクラスのMethodプロパティに「POST」を指定します。
Visual Basicの埋め込み式を用いて、XML 要素リテラルでtoastXml要素を作成しています。<wp:Text1>要素と<wp:Text2>要素の値に、メッセージが更新された旨を入力します。
XElement.ParseメソッドでtoastXmlの内容を文字列として読み込みます。
送信する通知のデータ本体を設定します。読み込んだXMLデータを、Encoding.UTF8.GetBytesメソッドでUTF8のバイトシーケンスにエンコードし、Byte型のmyNotificationMessage変数に格納します。
HttpRequestクラスのContentlengthにUTF8のバイトシーケンスにエンコードしたバイト数を指定します。ContentTypeにはtext/xml、HeadersにはAddメソッドで、「"X-WindowsPhone-Target", "toast"」と「"X-NotificationClass", "2"」を追加します。X-NotificationClassヘッダには、いつデバイスに通知するかを設定できます。”2”は「プッシュ通知サービスによって、すぐにメッセージを配信」する場合に指定します。”12”を指定すると「450 秒以内に、プッシュ通知サービスによってメッセージを配信」になり、”22”を指定すると「900 秒以内に、プッシュ通知サービスによってメッセージを配信」の意味になります。
要求データを書き込むために使用する Stream オブジェクトmyStreamを宣言します。 StreamクラスのWriteメソッドでByte型のmyNotificationMessageを書き込みます。Writeメソッドの書式は下記の通りです。

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

Closeメソッドで、Streamを閉じます。これで、Windows Phoneにトースト通知がなされます。
  Private Sub ToastMessage()
    Dim sendToastNotification As HttpWebRequest = DirectCast(WebRequest.Create(getUri), HttpWebRequest)
    sendToastNotification.Method = "POST"
  
    Dim toastXml As XDocument = <?xml version="1.0" encoding="utf-8"?>
              <wp:Notification xmlns:wp="WPNotification">
                <wp:Toast>
                  <wp:Text1>Messageが更新されました。</wp:Text1>
                  <wp:Text2>確認してください。</wp:Text2>
                    </wp:Toast>
                  </wp:Notification>
    Dim readXmlData As XElement = XElement.Parse(toastXml.ToString)
    Dim myNotificationMessage As Byte() = Encoding.UTF8.GetBytes(readXmlData.ToString)
 
    With sendToastNotification
        .ContentLength = myNotificationMessage.Length
        .ContentType = "text/xml"
        .Headers.Add("X-WindowsPhone-Target", "toast")
        .Headers.Add("X-NotificationClass", "2")
    End With
 
    Dim myStream As Stream = sendToastNotification.GetRequestStream()
    myStream.Write(myNotificationMessage, 0, myNotificationMessage.Length)
    myStream.Close()
  End Sub

ASP.NETページの作成(ChannelUri_NET)

VS2010のメニューから、「ファイル(F)/新規作成(N)/Webサイト(W)」と選択し、表示される画面から「ASP.NET Webサイト」を選択します。「webの場所(L)」に今回は「フォルダー名\ChannelUri_NET」と指定し[OK]ボタンをクリックします。このプロジェクトはWindows Phoneで取得されたChannelUriをサーバーに保存するプロジェクトです。

ソリューションエクスプローラー内のDefault.aspxを展開して表示される、Default.aspx.vbにリスト4のコードを記述します。

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

リスト4 (Default.aspx)

Option Strict On
Imports System.IO
Partial Class _Default
  Inherits System.Web.UI.Page

ページが読み込まれた時の処理

サーバー上の物理パスを指定します。
StreamReaderクラスで、POSTされたデータ(Request.InputStream)を取得します。StreamReaderクラスは、特定のエンコーディングのバイトストリームを読み込むTextReader を実装するクラスです。
取得したデータの内容をReadToEndメソッドで読み取り、変数readStrに格納しておきます。
フォルダー名とファイル名(channelUri.txt)を指定して、読み取ったデータをStreamWriterクラスのWriteメソッドで書き込みます。StreamWriterクラスは、文字を特定のエンコーディングでストリームに書き込むための TextWriterを実装するクラスです。
channelUri.txtにWindows Phoneから送信されたチャネルUriが保存されます。
  Private Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    Dim filePath As String = Server.MapPath("./")
    Dim reader As New StreamReader(Me.Request.InputStream(), System.Text.Encoding.UTF8)
    Dim readStr As String = reader.ReadToEnd
    Dim writer As StreamWriter = New StreamWriter(filePath & "SaveData/" & "channelUri.txt", False, System.Text.Encoding.UTF8)
    writer.Write(readStr)
    reader.Close()
    writer.Close()
    Response.Flush()
  End Sub
End Class

ASP.NETページの作成(Message_NET)

VS2010のメニューから、「ファイル(F)/新規作成(N)/Webサイト(W)」と選択し、表示される画面から「ASP.NET Webサイト」を選択します。「webの場所(L)」に今回は「フォルダー名\Message_NET」と指定し[OK]ボタンをクリックします。このプロジェクトはWPFで入力されたメッセージをXML形式でサーバーに保存するプロジェクトです。

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

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

リスト5 (Default.aspx.vb)

Option Strict On
Imports System.IO

Partial Class _Default
  Inherits System.Web.UI.Page

ページが読み込まれた時の処理

サーバー上の物理パスを指定します。
StreamReaderクラスで、POSTされたデータ(Request.InputStream)を取得します。StreamReaderクラスは、特定のエンコーディングのバイトストリームを読み込むTextReader を実装するクラスです。
取得したデータの内容をReadToEndメソッドで読み取り、変数readStrに格納しておきます。
フォルダー名とファイル名(messageInfo.xml)を指定して、読み取ったデータをStreamWriterクラスのWriteメソッドで書き込みます。StreamWriterクラスは、文字を特定のエンコーディングでストリームに書き込むための TextWriterを実装するクラスです。
messageInfo.xmlにWPFから送信されたメッセージの内容がXML形式で保存されます。
  Private Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    Dim filePath As String = Server.MapPath("./")
    Dim reader As New StreamReader(Me.Request.InputStream(), System.Text.Encoding.UTF8)
    Dim readStr As String = reader.ReadToEnd
    Dim writer As StreamWriter = New StreamWriter(filePath & "SaveData/" & "messageInfo.xml", False, System.Text.Encoding.UTF8)
    writer.Write(readStr)
    reader.Close()
    writer.Close()
    Response.Flush()
  End Sub
End Class

  • 「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メルマガ会員のサービス内容を見る

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