お天気情報WebAPIを使ってGIF画像を表示する
2012年1月27日(金)
お天気の情報とGIF画像を表示する処理
[<<]と[>>]ボタンタップで増減するメンバ変数noの値で、条件分岐を行います。noの値が0の時は、メンバ変数myNowにtoday(今日)を格納し、[<<]ボタンを使用不可に、[>>]ボタンを使用可とします。1の時は、myNowにtomorrow(明日)を格納します。2の時は、myNowにdayaftertomorrow(明後日)を格納し、[<<]ボタンを使用可能に、[>>]ボタンを使用不可とします。 メンバ変数noの値をAddDaysメソッドに指定し、短いタイプの日付を変数myDateに格納します。指定した日数を加算、減算するのにDateTimeのインスタンスからAddDaysメソッドを使用します。 ImageTools.IO.Decoders.AddDecoder(Of GifDecoder)() の1文を追加します。これはGIFを表示させるために、初期化の際に一度だけ必要な処理です。このまま覚えてください。 新しいExtendedImageクラスのインスタンス、myImageオブジェクトを作成します。ExtendedImageクラスは、Image クラスのピクセルを格納し、ファイルやストリームのサイズ変更やカッティングのような操作から、イメージを読み込む機能を提供するクラスです。 各市のお天気情報を表示するには、各市のidが必要です。このidは http://weather.livedoor.com/forecast/rss/forecastmap.xml から取得することができます。上記URLに移動してブラウザの「ソースの表示(V)」を選択して、ソースを表示させると、図3のような構造のXMLになっています。この中の<city>要素の”id”属性の値を取得する必要があります。
図3:forecastmap.xmlの構造(クリックで拡大) |
Uri型の変数myUriにhttp://weather.livedoor.com/forecast/rss/forecastmap.xmlのUriを格納しておきます。新しいWebClientのインスタンスmyWebClientオブジェクトを作成します。DownloadStringAsyncメソッドで、Uri として指定したリソースをダウンロードします。 AddHandler ステートメントでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラを追加します。イベント ハンドラ内では、ダウンロードされた文字列としての結果 XML(resultArgs.Result) をXElement.Parseメソッドで文字列として読み込みます。読み込んだXMLの<city>要素の”title”属性の値が、cityTextBox.Textの値と同じ<city>要素を選択するクエリを定義します。そのクエリ内を反復処理しながら変数resultに各要素を格納していきます。メンバ変数cityIdに<city>要素の属性”id”の値を格納します。数値型のメンバ変数myIdに数値に変換したcityIdの値を格納します。 新しいWebClientのインスタンス、wcオブジェクトを作成します。お天気情報のAPI へのリクエストは、対象となる「市」や表示する「日」などの条件を下記のような URL で指定します。(REST) Dim _uri As Uri = New Uri(String.Format("http://weather.livedoor.com/forecast/webservice/rest/v1?city={0}&day={1}", myId, myNow), UriKind.Absolute) cityには、先に取得した「市」のidが入ります。dayには変数myNowの値が入ります。myNowの値はメンバ変数noの値によって、today(今日)、tomorrow(明日)、dayaftertomorrow(明後日)と変化します。DownloadStringAsyncメソッドに、上記Uriを指定しソースをダウンロードします。 cityに「松山」のidである104を指定し、dayに「今日」を表すtodayを指定すると、図4のようなXMLが返ってきます。<image>要素の子要素<url>を見るとGIF画像が指定されています。ImageToolsを使用しなければ、この画像はWindows Phoneでは表示できません。
図4:結果XML(クリックで拡大) |
AddHandler ステートメントでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラを追加します。イベント ハンドラ内では、ダウンロードされた文字列としての結果 XML(myresultArgs.Result) をXElement.Parseメソッドで文字列として読み込みます。変数areaに、最初に見つかった<title>要素の値を格納します。地域名が格納されます。areaTextBlock内に変数areaの内容と、日付を格納した変数myDateの値を連結して表示します。 変数weatherに<Image>要素の子要素<title>要素の値を格納します。天気情報が格納されます。weatherTextBlockに変数weatherの値を表示します。変数gifUriに<image>要素の子要素<url>の値を格納します。お天気のGIF画像のURLが格納されます。ExtendedImageクラスのインスタンスである、myImageのUriSourceプロパティにgifUriのUriを絶対Uriで指定します。UriSourceプロパティでは、ExtendedImageのUriのソースを設定できます。Try~Catch~End Tryで例外処理を行います。例外が発生した場合はメッセージを表示し、[>>]ボタンの使用を不可として処理を抜けます。 GIF画像の読み込みが完了した時に発生する、LoadingCompletedイベントに、イベントハンドラを追加します。イベントハンドラ内では、Image1のSourceプロパティに、ExtendedImageクラスのインスタンス、myImageオブジェクトをBitmapに変換して指定しています。GIF画像を表示するには、Dispatcherが関連付けられているスレッドで、デリゲートを実行する必要があります。これには、非同期処理であるBeginInvokeメソッドを使用します。 Private Sub DataShow() Select Case no Case 0 myNow = "today" prevButton.IsEnabled = False nextButton.IsEnabled = True Case 1 myNow = "tomorrow" Case 2 myNow = "dayaftertomorrow" nextButton.IsEnabled = False prevButton.IsEnabled = True End Select Dim myDate As String= DateTime.Now.AddDays(no).ToShortDateString ImageTools.IO.Decoders.AddDecoder(Of GifDecoder)() Dim myImage As ExtendedImage = New ExtendedImage Dim myUri As Uri = New Uri("http://weather.livedoor.com/forecast/rss/forecastmap.xml", UriKind.Absolute) Dim myWebClient As New WebClient myWebClient.DownloadStringAsync(myUri) AddHandler myWebClient.DownloadStringCompleted, Sub(resultSender As Object, resultArgs As DownloadStringCompletedEventArgs) Dim xmldoc As XElement = XElement.Parse(resultArgs.Result) Dim query = From c In xmldoc.Descendants("city") Where c.Attribute("title").Value.Equals(cityTextBox.Text) Select c For Each result In query cityId = result.Attribute("id").Value myId = Integer.Parse(cityId) Next Dim wc As New WebClient Dim _uri As Uri = New Uri(String.Format("http://weather.livedoor.com/forecast/webservice/rest/v1?city={0}&day={1}", myId, myNow), UriKind.Absolute) wc.DownloadStringAsync(_uri) AddHandler wc.DownloadStringCompleted, Sub(myresultSender As Object, myresultArgs As DownloadStringCompletedEventArgs) Try Dim doc As XElement = XElement.Parse(myresultArgs.Result) Dim area As String = doc.Descendants("title").First.Value areaTextBlock.Text = area & "(" & myDate & ")" Dim weather As String = doc.Descendants("image").Elements("title").Value weatherTextBlock.Text = weather Dim gifUri As String = doc.Descendants("image").Elements("url").Value myImage.UriSource = New Uri(gifUri, UriKind.Absolute) Catch MessageBox.Show("市が不正です。") no = 0 nextButton.IsEnabled = False Exit Sub End Try End Sub End Sub AddHandler myImage.LoadingCompleted, Sub(loadSender As Object, loadArgs As EventArgs) Dispatcher.BeginInvoke(Sub() Image1.Source = myImage.ToBitmap End Sub) End Sub End Sub
[>>]ボタンがタップされた時の処理
メンバ変数noの値が2の場合はnoの値は2とします。それ以外の場合は、メンバ変数noの値を1ずつ増加させます。[>>]ボタンの使用を可能とします。お天気情報を表示するDataShowプロシージャを実行します。 Private Sub nextButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles nextButton.Click If no = 2 Then no = 2 Else no = no + 1 nextButton.IsEnabled = True End If DataShow() End Sub
[<<]ボタンがタップされた時の処理
メンバ変数noが0の場合はnoの値は0とします。それ以外の場合は、メンバ変数noの値を1ずつ減少します。[<<]ボタンの使用を可能とします。お天気情報を表示するDataShowプロシージャを実行します。 Private Sub prevButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles prevButton.Click If no = 0 Then no = 0 Else no = no - 1 prevButton.IsEnabled = True End If DataShow() End Sub End Class
「お天気情報WebAPIを使ってGIF画像を表示する」のサンプルプログラム
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。