使ってみよう! Windows Live SDK/API

第27回Live FrameIt SDK ─⁠─ 仮想フォトフレームの作成(2)

はじめに

前回に引き続きLive FrameItのSDKを利用した仮想フォトフレームアプリケーションの作成です。今回はユーザーのコレクションを取得してLive FrameItから配信される画像を取得・表示まで行います。また、今回は仮想フォトフレームとなる図1のようなアプリケーションを作成しながら進めます。

図1 仮想フォトフレーム
図1 仮想フォトフレーム

作成するサンプルアプリケーションのソースコードは、この記事の最終ページからダウンロードできます。

登録トークンを使用したデイバスIDの取得

前回デバイスをLive FrameItに登録するために必要なデバイスIDの取得方法を紹介しました。その際にWindows Live IDアカウントによるユーザー認証をデバイス(またはアプリケーション)側で実装するものと、Live FrameItのWebサイトで行う方法によるもののうち、前者のコードを示しました。今回の最初は後者のコードを簡単に紹介します。Windows Live ID Client SDKを使用しないため、たいていのプログラミング言語で実装が可能です。ただし紹介するコードは前回同様VB.NETです。

デバイス側でLive IDアカウントによるユーザー認証を行わない代わりに登録トークンという文字列を使用してデバイスをLive FrameItへ登録します。詳しい手順は前回を参照してください。

登録トークンの取得

まずデバイスは、登録トークンをLive FrameItサービスへ要求し取得します。Webサービスを呼び出すためにサービス参照を追加する必要があります。こちらも詳しくは前回を参照してください。登録トークンの取得には、サービス参照によって作成されたクラスDeviceSvcSoapClientクラスのGetClaimTokenメソッドを使用します。メソッドの引数は、製造元の名前とシリアル番号です。いずれも64文字以下で自由に設定します。

' (注: まだ不完全な例です)
Dim client = New DeviceSvcSoapClient
Dim manufacturerId = "Virtual Photo Frame"
Dim serialNumber = Now.Ticks.ToString
Dim result = client.GetClaimToken(manufacturerId, serialNumber)
Dim calimToken = result.ClaimToken

GetClaimTokenメソッドの戻り値は、GetClaimTokenResults型です。このクラスの持っているClaimTokenプロパティを参照すると登録トークンが取得できます。この取得したトークンをユーザーに提示し、Live FrameIt Webサイト図2でトークンをユーザーに入力してもらいます。GetClaimTokenResults.ClaimUrlプロパティを参照するとユーザーがトークンを入力するWebページのアドレスを取得できます。

図2 登録トークンの入力
図2 登録トークンの入力

デイバスIDの取得

ユーザーによる登録トークンの入力が完了すると、登録トークン要求時に指定した製造元の名前とシリアル番号および取得した登録トークンを使用して、デバイスIDが取得できます。取得にはDeviceSvcSoapClientクラスのDeviceBindメソッドを使います(前回はDeviceBindUserメソッドを使いました⁠⁠。Live IDアカウントのユーザー認証がないためHTTPヘッダーフィールドの追加など前回のような複雑な処理は必要ありません。以下に一連のコードを示します。

Private Sub RegisterDeviceWithToken()
    Dim result As DeviceBindResults
    Using client = New DeviceSvcSoapClient
        Dim manufacturerId = "Virtual Photo Frame" '製造元の名前
        Dim serialNumber = Now.Ticks.ToString ' シリアル番号

        ' 登録トークンの取得
        Dim tokenResult = client.GetClaimToken(manufacturerId, serialNumber)
        If tokenResult.ResponseCode <> 0 Then
            ' (ResponseCode = 1 のとき取得失敗)
            Exit Sub
        End If

        ' ユーザーにトークンの提示
        MessageBox.Show(tokenResult.ClaimUrl & " へアクセスして登録トークン " & _
                        tokenResult.ClaimToken & " を設定してください。" & vbCrLf & _
                        "設定完了後 OK ボタンをクリックしてください。")

        ' デバイスIDの取得
        result = client.DeviceBind(tokenResult.ClaimToken, manufacturerId, serialNumber)
    End Using

    If result.ResponseCode = 0 Then
        ' 取得成功 (ResponseCode = 0)

        ' デバイスIDの保存例 (プロジェクトのプロパティの設定で String型の DeviceId という値を追加しておきます)
        My.Settings.DeviceId = result.DeviceId
        My.Settings.Save()
    End If
End Sub

UIの作成

デバイスIDの取得後は、コレクションを取得し、コレクションの各画像を取得・表示処理という流れなりますが、ここで冒頭の図でも見せた仮想フォトフレームのUIを作成しようと思います。本連載の趣旨とは少しはずれますので簡単に済ませて次に進みましょう。作るのはLive FrameItから配信された画像を表示する最低限程度のものとなっています。これを参考にまたは独自に作りこんで頂けると幸いです。

プロジェクトの作成

Visual StudioのプロジェクトはWPFアプリケーションを選択します図3⁠。必要なWebサービス参照の追加などはこれまでの内容を元に設定してください。

図3 WPFアプリケーションプロジェクトの作成
図3 WPFアプリケーションプロジェクトの作成

デザイン

見た目の部分はXAMLファイルに記述します。プロジェクト作成後にはWindow1.xamlというファイルがあるので、これの名前を変更(ファイル名だけでなくクラス名も変更する)して編集しています。図4にデザイナ画面を示します。

図4 デザイナ画面
図4 デザイナ画面

今回作成するアプリケーションは、ウィンドウを透明にし、その上に取得した画像と枠となる画像を重ねて表示しています。また、終了や表示するコレクションの選択など操作は右クリックメニューに用意しています図5⁠。

図5 右クリックメニュー
図5 右クリックメニュー

以下にXAMLファイルの内容を示します。ウィンドウや画像の大きさや位置は、用意した画像に併せて適当に設定します。

<Window x:Class="FrameWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:me="clr-namespace:VirtualPhotoFrame"
        Title="仮想フォトフレーム" Width="800" Height="750"
        AllowsTransparency="True" WindowStyle="None" Background="Transparent" ResizeMode="NoResize"
        MouseLeftButtonDown="Window_MouseLeftButtonDown" >
    <Grid>
        <Grid.ContextMenu>
            <ContextMenu>
                <ContextMenu.CommandBindings>
                    <CommandBinding Command="{x:Static me:FrameWindow.SelectCollectionCommand}" 
                                    Executed="SelectCollectionCommand_Executed" />
                </ContextMenu.CommandBindings>
                <MenuItem Header="デバイスの登録" Click="RegisterMenuItem_Click" />
                <MenuItem Header="コレクションの選択" x:Name="CollectionMenuItem">
                    <MenuItem.ItemContainerStyle>
                        <Style TargetType="MenuItem">
                            <Setter Property="Header" Value="{Binding Name}" />
                            <Setter Property="Command" Value="{x:Static me:FrameWindow.SelectCollectionCommand}" />
                            <Setter Property="CommandParameter" Value="{Binding FeedUrl}" />
                        </Style>
                    </MenuItem.ItemContainerStyle>
                </MenuItem>
                <MenuItem Header="コレクションの再取得" Click="GetCollectionMenuItem_Click" />
                <Separator />
                <MenuItem Header="終了" Click="ExitMenuItem_Click" />
            </ContextMenu>
        </Grid.ContextMenu>
        <Grid Background="Black" Margin="157,170,141,182" Width="480" Height="360" />
        <!-- ↓ Live FrameIt から配信された画像を表示 -->
        <Image  x:Name="PhotoImage" Margin="157,170,141,182" Width="480" Height="360" />
        <!-- ↓ Live FrameIt の画像の上に表示する額の画像 -->
        <Image Source="frame.png" />
    </Grid>
</Window>

ユーザーのコレクションの数によってメニューの項目数も変わります。この部分はWPFの特徴であるバインディングやコマンドという機能を使用して実装します。それ以外のユーザー操作による処理部分はWindows.Formsのときと同様なイベントを用いて処理することにします。

設定の保存

デバイスIDや表示するコレクションのRSSフィードのURLを保存するために、アプリケーション設定機能をします。プロジェクトのプロパティの設定タブから図6のように保存用の項目を追加します。

図6 アプリケーション設定
図6 アプリケーション設定

DeviceIdとCollectionFeedUrlという項目を追加しました。

コードの記述

本題ではないメニューのクリックイベント処理部分などをまとめて以下に示します。.xaml.vbファイルに記述します。

Imports VirtualPhotoFrame.ServiceReference
Imports Microsoft.WindowsLive.Id.Client
Imports System.Net
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Syndication ' System.ServiceModel.Web を参照追加します
Imports System.Threading
Imports System.Windows.Threading

Class FrameWindow
    Public Shared ReadOnly SelectCollectionCommand As RoutedCommand = _
        New RoutedCommand("SelectCollection", GetType(FrameWindow))



    Private Sub Window_MouseLeftButtonDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
        ' ウィンドウをドラッグで移動できるようにする
        DragMove()
    End Sub

    Private Sub RegisterMenuItem_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        ' RegisterDevice: 前回紹介したデバイスの登録手続きを記述したメソッド
        ' 取得したデバイス ID は アプリケーション設定保存する
        '   My.Settings.DeviceId = result.DeviceId
        '   My.Settings.Save()
        RegisterDevice()
    End Sub

    Private Sub ExitMenuItem_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        ' アプリケーションの終了
        Me.Close()
    End SubEnd Class

この後も、このファイルにコードを追記していきます。

コレクションの取得

それではコレクション情報を取得してみましょう。デバイスIDを取得するとユーザーのコレクションを取得できるようになります。取得には、サービス参照によって作成されたクラスDeviceSvcSoapClientクラスのGetCollectionInfoメソッドを使用します。引数はデバイスIDです。

Using client = New DeviceSvcSoapClient
    Dim results = client.GetCollectionInfo("取得したデバイス ID")
    If results.ResponseCode = 0 Then
        ' 取得成功 (ResponseCode = 0)

        ' コレクション名と RSS フィード URL の表示
        For Each l In results.CollectionInfoList
            Console.WriteLine("Name: {0}, Url: {1}", _
                              l.Name, _
                              l.FeedUrl)
        Next
    End If
End Using

戻り値のCollectionInfoListプロパティを参照すると、ユーザーのコレクション情報が得られます。コレクション情報には、ユーザーが指定したコレクション名と、Live FrameItが生成したコレクションのRSSフィードのURLが含まれています。それぞれ、CollectionInfoクラスのNameとFeedUrlプロパティとして参照できます。

作成中のアプリケーションのコードには次のようにメソッド化したものを追記しておきましょう。またコレクションの再取得メニューをクリック時にメソッドを呼び出すようにします。

Private Sub GetCollectionInfo()
    Using client = New DeviceSvcSoapClient
        Dim results = client.GetCollectionInfo(My.Settings.DeviceId)
        If results.ResponseCode <> 0 Then
            MessageBox.Show("コレクションの取得に失敗しました。")
            Exit Sub
        End If
        ' コレクションをメニューに設定
        CollectionMenuItem.ItemsSource = results.CollectionInfoList
    End Using
End Sub

Private Sub GetCollectionMenuItem_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    ' コレクションの取得
    GetCollectionInfo()
End Sub

コレクションが取得できたら、コレクション名をユーザーに提示し、デバイスで表示するコレクションを決定します。今回作成するアプリケーションではメニューをクリックすることでコレクションを選択します。以下のコードがコレクションのメニューをクリック時に呼ばれる処理になります。

Private Sub SelectCollectionCommand_Executed(ByVal sender As System.Object, ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
    ' コレクションの選択

    ' コレクション RSS フィード URL の保存
    Dim url = CStr(e.Parameter)
    My.Settings.CollectionFeedUrl = url
    My.Settings.Save()

    ' RSS フィード 取得
    Dim thread = New System.Threading.Thread(AddressOf FetchFeed)
    thread.Start(url)
End Sub

フィードURLの保存後、RSSフィード取得処理に遷移します。上記コード内にあるFetchFeedメソッドはこの後作成します。

RSSフィードの解析

コレクションの取得でコレクションのURLが取得できました。この実体はRSSフィードのURLです。デバイスはRSSフィードを解析してユーザー所望の画像を表示します。それでは、RSSフィードを取得し、デバイスに必要な処理を順に実装していきます。

RSSフィード取得時の処理はFetchFeedというメソッドを作りその中に記述していくことにします。このメソッドと、この後必要となる記述を次のようにコードに追加してください。

' RSS フィード更新用タイマー
Private WithEvents FeedTimer As New DispatcherTimer
' スライドショー(画像切り替え)表示用タイマー
Private WithEvents SlideShowTimer As New DispatcherTimer

' 画像 URL から保存したファイル名を参照するための Dictionary
Private CachedImages As New Dictionary(Of String, String)
Private CachedImagesLock As New ReaderWriterLockSlim

' スライドショー用の List, 表示順に 画像 URL を格納
Private SlideShowImageUrls As New List(Of String)
Private SlideShowIndex As Integer
Private SlideShowImageUrlsLock As New ReaderWriterLockSlim

Private Sub FetchFeed(ByVal state As Object)
' (RSS フィード取得処理を記述) 
End Sub

RSSフィードの取得とそのタイミング

Live FrameItから配信される画像には天気予報やニュースなど時間経過とともに表示する価値が失われるもの、またユーザーが表示時間帯を設定したものなどが含まれているものがあります。デバイスはこれらを適切に表示しなければいけません。そのためにLive FrameItが発行するRSSフィードにはそのフィードの有効期限が含まれています。これを利用してデバイスは、適切なタイミングでRSSフィードを再取得します。

GetCollectionInfoメソッドでは次のようなRSSフィードのURLが得られます。

http://rss.frameit.com/GenRss/genrss.ashx?id=...&pin=...

※pinパラメータはユーザーが暗証番号(シークレットナンバー)
設定していない場合ありません。

このURL先の内容を確認してみましょう。フィードの先頭部分は次のような構成になっています。

<?xml version="1.0" encoding="utf-8" ?> 
<rss version="2.0" xmlns:frameit="http://www.frameit.live.com/firss/" xmlns:media="http://search.yahoo.com/mrss/">
        <channel>
                <ttl>53</ttl> 
                <title>旅行写真</title> 
                <link>http://frameit.live.com</link> 
                <generator>http://frameit.live.com</generator> 
                <lastBuildDate>Tue, 13 Oct 2009 08:05:15 -0700</lastBuildDate> 
                <pubDate>Tue, 13 Oct 2009 08:05:15 -0700</pubDate> 
                <description />
                <item>
                ...

<ttl>と<pubDate>という項目がフィードに含まれていることがわかります。ttlはTime-to-Liveの略語で、フィードの有効期間を示す値(分: Minute)が設定されています。そして、pubDateはデバイスがフィードを要求した日時です。pubDateの日時にttl分を加算した日時が、フィードを再取得するタイミングとなります。

では、ここまでをコードで書きます。RSSフィードの解析はXMLとして処理してもいいですが、フィードを表すSyndicationFeedクラスが.NET Frameworkにはありますので、今回はこれを使用します。使用するにはプロジェクトにSystem.Web.Servicesの参照を追加する必要があります。

' (FetchFeed メソッド内に追記)
FeedTimer.Stop()
SlideShowTimer.Stop()

' RSSフィード取得
Dim url = CStr(state) ' RSS フィード URL
Dim feed As SyndicationFeed
Try
    feed = SyndicationFeed.Load(Xml.XmlReader.Create(url))
Catch ex As Exception
    ' 取得できなかった場合、時間を置いて再度取得する
    FeedTimer.Interval = New TimeSpan(0, 1, 0)
    FeedTimer.Start()
    SlideShowTimer.Start()
    Exit Sub
End Try

' 有効時間(分)取得
Dim ttl = (From ext In feed.ElementExtensions _
           Where ext.OuterName = "ttl" _
           Select ext.GetObject(Of Integer)()).SingleOrDefault

' フィードの発行日時取得
Dim pubDate = (From ext In feed.ElementExtensions _
               Where ext.OuterName = "pubDate" _
               Select ext.GetObject(Of String)()).SingleOrDefault

' 次回フィード取得時間を求めタイマーを設定
Dim span = CDate(pubDate).AddMinutes(ttl).Subtract(Now) ' 次回フィードするまでの時間
FeedTimer.Interval = span
FeedTimer.Start()

フィード取得はタイマーを用いて定期的に取得するため、タイマー用の処理をいろいろと記述していますが、要となる部分は、SyndicationFeed.Loadメソッドによるフィードの取得と得られたfeedオブジェクから<ttl>と<pubDate>要素を参照しているところです。<ttl>、<pubDate>ともRSS 2.0の仕様に定義されたものですが、SyndicationFeedクラスでは対応するプロパティが定義されていないため上記コードのようにElementExtensionsプロパティを使用して参照しています。

画像のダウンロード

続いてフィードに含まれている複数の<item>要素をみていきましょう。ひとつの<item>要素は次のような構成になっています。

<item>
        <frameit:sourceIcon>http://image.frameit.com/GenImage/source.ashx?sq=1&st=6&mkt=ja-jp</frameit:sourceIcon> 
        <frameit:sourceCategory>ニュースと情報</frameit:sourceCategory> 
        <frameit:sourceName>天気予報</frameit:sourceName> 
        <title>東京都 東京</title> 
        <link>http://1.image.frameit.com/GenImage/Item.ashx?...</link> 
        <category>東京都 東京</category> 
        <guid isPermaLink="true">http://1.image.frameit.com/GenImage/Item.ashx?...</guid> 
        <description>
        <![CDATA[ <img src="http://1.image.frameit.com/GenImage/Item.ashx?..." /><br/>東京都 東京
        ]]> 
        </description>
        <pubDate>Tue, 13 Oct 2009 08:05:15 -0700</pubDate> 
        <enclosure type="image/jpeg" url="http://1.image.frameit.com/GenImage/Item.ashx?..." /> 
        <media:content type="image/jpeg" width="480" height="400" url="http://1.image.frameit.com/GenImage/Item.ashx?..." /> 
        <media:thumbnail width="77" height="64" url="http://1.image.frameit.com/GenImage/Item.ashx?...&thumb=1" /> 
</item>

例はLiveFrame Itで生成された天気予報の画像です。デバイスが参照すべき画像のURLが<link>や<guid>などの多数の要素に含まれています。ただし、Live FrameItは画像URLを<media:content>、<enclosure>、<description>要素のうちからデバイスが参照することを想定して配信していますので、この3要素の中からデバイスに併せて選択し使用します。

デバイスは、画像表示に関して以下の動作が求められます。

  • 画像はダウンロードしてデバイスのストレージにキャッシュしておく
  • フィードに記載された順に画像を表示する

キャッシュ動作は、ネットワークが常に接続されている状態とは限りませんので接続している間にダウンロードし、ネットワークが切断されているときも画像表示を可能にします。また同じ画像を表示する場合にネットワーク接続回数を削減できます。

フィードに記載された順に表示する理由は、Live FrameItのWebサイト上でユーザーはコレクションの表示順についても設定しているためです。デバイス側で表示順を変更するべきではありません。

以上の動作に加えて、先ほどのフィード再取得を行います。もし再取得時にネットワークが接続されていない場合は、キャッシュ済みの画像を表示し、ネットワーク回復後にフィードを更新するようにします。フィード更新により、新しい画像はダウンロードし、フィードから消えた古い画像はキャッシュからも削除するようにしましょう。

フィードから画像URLを参照するコードは次のようになります。今回は<media:content>要素からURLを取得しています。

' スライドショーの URL リストをクリア
SlideShowImageUrlsLock.EnterWriteLock()
SlideShowImageUrls.Clear()
SlideShowImageUrlsLock.ExitWriteLock()

' フィードから画像 URL 参照
Dim newImages = New List(Of String)
For Each item In feed.Items
    '  の url 属性値取得
    Dim imageUrl = (From ext In item.ElementExtensions _
                    Where ext.OuterName = "content" _
                    AndAlso ext.OuterNamespace = "http://search.yahoo.com/mrss/" _
                    Select ext.GetReader.GetAttribute("url")).SingleOrDefault

    ' 取得順にリストへ画像 URL を追加
    SlideShowImageUrlsLock.EnterWriteLock()
    SlideShowImageUrls.Add(imageUrl)
    SlideShowImageUrlsLock.ExitWriteLock()

    newImages.Add(imageUrl)
Next

取得したURLの順は記憶しておく必要があるので、コレクション(ここではList(Of String)クラスなどのこと)操作も含まれています。

続いて画像のダウンロード部分を以下に示します。2回目以降のフィード取得時の動作も考慮して画像の削除を行ってから、新しい画像のみダウンロードしています。

' フィードにない画像ファイル削除
Dim deletedKeys = New List(Of String)
For Each k In CachedImages.Keys
    If newImages.Contains(k) Then
        Continue For
    End If
    Try
        CachedImagesLock.EnterReadLock()
        My.Computer.FileSystem.DeleteFile(CachedImages(k))
        deletedKeys.Add(k)
    Catch ex As Exception
        ' Ignore
    Finally
        CachedImagesLock.ExitReadLock()
    End Try
Next

' リストから古い画像URLを削除
CachedImagesLock.EnterWriteLock()
For Each k In deletedKeys
    CachedImages.Remove(k)
Next
CachedImagesLock.ExitWriteLock()

' 新しい画像をダウンロード
For Each u In newImages
    CachedImagesLock.EnterReadLock()
    Dim contains = CachedImages.ContainsKey(u)
    CachedImagesLock.ExitReadLock()
    If contains Then
        Continue For
    End If

    ' 新しくダウンロード
    Try
        Dim client = New WebClient
        Dim file = System.IO.Path.Combine(CachePath, Guid.NewGuid.ToString)
        client.DownloadFile(u, file)
        CachedImagesLock.EnterWriteLock()
        CachedImages.Add(u, file)
        CachedImagesLock.ExitWriteLock()
    Catch ex As Exception
        ' Ignore
    End Try
Next

以上が、FetchFeedメソッド内のコードです。このコードはタイマーのTickイベントで別スレッドとして実行するようにしておきます。また、アプリケーション起動時にも既にコレクションのURLがある場合は呼び出されるようにします。

Private Sub FeedTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles FeedTimer.Tick
    FeedTimer.Stop()

    ' RSS フィード 再取得
    Dim thread = New System.Threading.Thread(AddressOf FetchFeed)
    thread.Start(My.Settings.CollectionFeedUrl)
End Sub

Private CachePath As String = System.IO.Path.Combine(My.Application.Info.DirectoryPath, "cache")
Private Sub FrameWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    ' 画像をダウンロードするフォルダ作成
    My.Computer.FileSystem.CreateDirectory(CachePath)
    If My.Settings.DeviceId =  Then
        Exit Sub
    End If

    ' コレクションの取得、メニュー設定
    GetCollectionInfo()

    ' RSS フィード 読み出し
    If My.Settings.CollectionFeedUrl <>  Then
        Dim thread = New System.Threading.Thread(AddressOf FetchFeed)
        thread.Start(My.Settings.CollectionFeedUrl)
    End If
End Sub

画像の表示

最後にダウンロードした画像をウィンドウに表示する処理を書いて完了です。以下のようにスライドショー用のタイマーのTickイベントに処理を記述します。

Private Sub SlideShowTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles SlideShowTimer.Tick
    SlideShowTimer.Stop()

    ' 表示する画像の URL を List から取得
    Dim url As String
    Dim count As Integer
    SlideShowImageUrlsLock.EnterReadLock()
    url = SlideShowImageUrls(SlideShowIndex)
    count = SlideShowImageUrls.Count
    SlideShowImageUrlsLock.ExitReadLock()

    ' ダウンロードした画像があるかどうか
    Dim exists As Boolean
    Dim file As String = 
    CachedImagesLock.EnterReadLock()
    If CachedImages.ContainsKey(url) Then
        file = CachedImages(url)
        exists = System.IO.File.Exists(file)
    Else
        exists = False
    End If
    CachedImagesLock.ExitReadLock()

    ' 画像がある場合、Image コントロールに設定
    If exists Then
        Try
            PhotoImage.Source = New BitmapImage(New Uri(file))
        Catch ex As Exception
        End Try
    End If

    ' List の Index 値をインクリメントまたは 0 に戻す
    Dim prevIndex = Interlocked.Increment(SlideShowIndex)
    If prevIndex >= count - 1 Then
        Interlocked.Exchange(SlideShowIndex, 0)
    End If

    ' 次回画像表示用にタイマーを設定
    SlideShowTimer.Interval = New TimeSpan(0, 0, 10)
    SlideShowTimer.Start()
End Sub

以上です。実際に実行して動作を確認してみましょう。Live FrameItサービス以外で提供された画像は既にインターネット上から削除されていたり、画像としてファイルを読み込みなかったりするかもしれません。そういった場合も考慮した実装が必要です。

おわりに

今回はここまでです。いかがでしたでしょうか。アプリケーションの動作のためコード量が少し多かったですが、Live FrameItサービスとのやりとり部分やフィードの解析自体はそう難しいものではなかったと思います。

作成した仮想フォトフレームアプリケーションのソースコードは、下記のリンクからダウンロードできます。参考にしてみてください。記事中に記載しきれなかった内容も含まれています。また、一部のコードは記述を変更しています。

次回もLive FrameItのSDKについてです。今回紹介しきれなかった内容を扱う予定です。

おすすめ記事

記事・ニュース一覧