Alive with activity、パート 2: ライブ タイルのサービスの作成とデバッグ
このシリーズのパート 1 では、Windows 8 の全体的なユーザー エクスペリエンスに "aliveness (常に動きがあること)" という感覚をもたらすタイル更新、バッジ更新、トースト通知の性質について説明しました。特に、XML ペイロードを使ってこれらの通知を生成する方法について見ていきました。このような XML ペイロードは、実行中のアプリやバックグラウンド タスクからローカルに発行することも、オンライン サービスの要求に応じて提供することもできます。
実行中のアプリから XML ペイロードを生成して発行する処理は、Visual Studio Ultimate 2012 または Visual Studio Express 2012 for Windows 8 を使ってアプリ内で簡単に開発およびデバッグできます。アプリのタイルとバッジのサンプル (英語)、セカンダリ タイルのサンプル (英語)、およびスケジュール通知のサンプル (英語) には、この場合に必要なものがすべて揃っています。
これよりも少し手間がかかるのは、定期的な更新とプッシュ通知をサポートする Web サービスの開発とデバッグです。このようなケースのクライアント側は、「プッシュおよび定期通知のクライアント側のサンプル」(英語) がたいへん参考になりますが、このサンプルを利用するには、サンプルと連携するサービスが必要です。この記事では、タイル更新とバッジ更新のための定期通知をサポートするサービスの開発方法について具体的に説明します。Visual Studio ツールと localhost を使って、サービスを運用環境に展開する前にデバッグする方法にも焦点を当てていきます。また、Windows Azure モバイル サービスをこの目的で使う方法についても簡単に触れます。パート 3 で説明しますが、Windows Azure モバイル サービスはプッシュ通知のサポートにも非常に便利です。
サービスの基本的な性質
タイルとバッジの定期更新をサポートするサービスとは、実際にはどのような動作をするものでしょうか。これまで主にクライアント アプリを扱ってきた開発者にとって、"サービス" という言葉はどちらかというと取りつきにくいので、まずこの言葉の意味を確認しましょう。
ごく簡単に言えば、サービスとは Web サーバー上にあるコードで、HTTP 要求が送られたときに "そのサーバー上で" 実行されるものです。これは HTML ページ (.htm または .html) の動作とは異なります。HTML ページにはサーバー側のコードがないため、サーバーは単純にそのページのテキストを返し、すべての処理は (そのページに含まれるクライアント側スクリプトの実行も含めて) クライアント側で行われます。一方、php、asp、aspx、cgi、cshtml、その他さまざまなサーバー側の拡張子で終わるページへの URI がある場合は、この最も基本的な意味での "サービス" と通信することになります。
サービスは、クライアントの HTTP 要求を受信し、URI に引数が含まれている場合はそれを処理して、適切なテキスト応答を返します。PHP や ASP.NET などのテクノロジで記述された "Web ページ" の場合、応答は HTML になります。Facebook や Twitter など (他にも多数)、Web API を実装するサービスの場合は、通常、URI クエリ文字列 (または要求ヘッダー) を通じて任意の数のパラメーターを受け取り、XML または JSON データを応答として返します (ここで説明しているサービスとは、SOAP ではなく Representational State Transfer (REST) を基盤とするサービスです。現在のサービスでは、REST が最も一般的に利用されています)。
したがって、タイルやバッジの定期更新を提供するサービスとは、タイルまたはバッジの更新のためにアプリから Windows に渡される任意の URI に存在し、HTTP 要求に対して適切な XML ペイロードで応答するサービスのことです。そのペイロードにはサポートされているテンプレートのいずれかに対応する要素が含まれ、イメージは他の URI として参照されます (インライン エンコーディングはサポートされていません)。ペイロードに含める特定の情報は、他の任意のソースから取得することもできます。これについては後で説明します。
このようなサービスは、細かい部分には違いがあるとしても、いずれも要求を受け取って処理し、XML 応答を構築するという点で共通した構造を持っています。以降では、その基本構造を作成する方法を見ていきましょう。
サービスの記述
サービスの記述とデバックには、サーバー側の言語として選んだ言語がサポートされていれば、どのツールを使ってもかまいません。この記事では、Visual Studio、中でも Visual Studio Ultimate 2012 と Visual Studio Express 2012 for Web を使って説明します。後者は、既にご存知の Windows 版と同様に無料で提供されています。Visual Studio Express 2012 for Web をインストールするには、Web Platform Installer (英語) を実行します。このインストーラーでは、PHP や WebMatrix などの他のさまざまな関連テクノロジもインストールでき、さまざまな言語でサービスを作成できるようになります。
非常にシンプルな例として、バッジ更新用の XML ペイロードを応答として返す完全な PHP サービスのコードを以下に示します。このペイロードでは、バッジの値が (サーバーのロケール設定に従って) その月の現在の日にちに設定されます。これは、拙著の無料の電子ブック『HTML、CSS、JavaScript を使った Windows 8 アプリ開発』(英語) の第 13 章で紹介した HelloTiles サンプル サイトからの抜粋です。
<?php echo '<?xml version="1.0" encoding="utf-8" ?>'; echo "<badge value='".date("j")."'/>"; ?>
このサービスは直接試すことができます。このデモ用に作成した Windows Azure サイトへのリンク https://programmingwin8-js-ch13-hellotiles.azurewebsites.net/dayofmonthservice.php をクリックしてください。次のような XML が返されます。
<?xml version="1.0" encoding="UTF-8"?> <badge value="24"/>
同じ URI を、「プッシュおよび定期通知のクライアント側のサンプル」(英語) のシナリオ 5「バッジ更新のポーリング」(英語) で試してみましょう。このアプリを (Visual Studio Express for Windows で) 初めて実行すると、次のようなタイルがスタート画面に表示されます。
今度は、上記の URI をシナリオ 5 のテキスト ボックスに入力し、[Start periodic updates] (定期更新の開始) をクリックします。ネットワークに接続していると、サンプルのタイルに数値のバッジが表示されます。
アプリが定期更新を開始したらすぐに、Windows はポーリングを実行して更新の有無を確認するようになり、その後は一定の間隔でポーリングを続行します。
より詳細な PHP のサンプルについては、「優れたタイル エクスペリエンスを開発する (パート 2)」を参照してください。この記事では、タイル更新の他のカスタマイズについても紹介しています。このサンプルでは、架空の get_trucks_from_database 関数によって、URI のクエリ文字列パラメーターに含まれる郵便番号を使ってデータベースにクエリを送り、このクエリの結果を使って XML 応答を作成します。
このようなコードのほかに、サービスで追加できる処理にはさまざななものがあります。以下に例を示します。
- 上記のような日にちを表示する PHP サービスでは、サーバーが別のタイム ゾーンに置かれていることもよくあります。アプリでクエリ文字列にローカル タイム ゾーンを指定すると、より正確な日付を取得できます。
- 天気予報サービスでは、URI に緯度と経度の値を設定し、目的の場所の現在の天気を取得できます。
- サービスによってイメージをその場で生成して Web サーバーに保存し、適切な URI を XML ペイロードに挿入できます。
- サービスから独自の要求を他のサービスに送信して、クエリ文字列パラメーターでカスタマイズされた追加データを取得します (これについては後で詳述します)。
- アプリでタイル更新のキューを有効にすると (EnableNotificationQueue メソッドを参照)、定期更新のためにポーリングする URI を 5 つまで指定できます。これについては、「プッシュおよび定期通知のクライアント側のサンプル」(英語) のシナリオ 4 で実際の動作を確認できます。タイル更新のキューには、各 URI からの更新が格納されます。もちろん、それぞれの URI は独自のクエリ文字列を使って細かくカスタマイズできるため、同一のサービスですべての要求に対応することができます。
- アプリでクエリ文字列にユーザー ID を含めると、サービスからデータ ストアを照会して、ユーザーの運動の履歴やゲームのハイ スコア、ユーザーが登録しているフィードからのニュースなどを取得できます。このような場合、ユーザー ID は個人を特定できる情報 (PII) になり得るため、アプリでプライバシーの問題を考慮することが重要です。つまり、クエリ文字列に含まれるユーザー名を暗号化するか、https:// URI を使う必要があります。
注: Windows の定期更新のメカニズム自体には、サービスを使ってユーザーを認証するための手段は含まれていません。このレベルのサポートは、プッシュ通知を利用する場合 (または、マニフェストでエンタープライズ認証機能を宣言しているエンタープライズ シナリオで) のみ可能です。
もちろん、サービスは他のテクノロジでも記述できます。強力な選択肢の 1 つに ASP.NET があります。ASP.NET では、アプリで使えるものと同じ NotificationsExtensions ライブラリ (C#) を利用して、適切な構造の XML ペイロードを簡単に生成できます。
簡単なサンプルを確認する場合は、拙著の第 13 章の HelloTiles サンプル用に作成した、非常に基本的な WebMatrix サービス I (付属のコンテンツを参照、英語) を参照してください。これは、一定の XML ペイロードを返すだけのサービスです (正方形とワイドのタイルの両方に対するバインドが設定されます)。構造的には、「優れたタイル エクスペリエンスを開発する (パート 2)」の 1 つ目の ASP.NET サンプルに似ています。
@{ // // This is where any other code would be placed to acquire the dynamic content // needed for the tile update. In this case we'll just return static XML to show // the structure of the service itself. // var weekDay = DateTime.Now.DayOfWeek; } <?xml version="1.0" encoding="utf-8" ?> <tile> <visual lang="en-US"> <binding template="TileSquarePeekImageAndText02" branding="none"> <image id="1" src="https://www.kraigbrockschmidt.com/images/Liam07.png"/> <text id="1">Liam--</text> <text id="2">Giddy on the day he learned to sit up!</text> </binding> <binding template="TileWideSmallImageAndText04" branding="none"> <image id="1" src="https://www.kraigbrockschmidt.com/images/Liam08.png"/> <text id="1">This is Liam</text> <text id="2">Exploring the great outdoors!</text> </binding> </visual> </tile>
このサービスは https://programmingwin8-js-ch13-hellotiles.azurewebsites.net/Default.cshtml (英語) に展開されているので、「プッシュおよび定期通知のクライアント側のサンプル」のシナリオ 4 を使って試すことができます。実行してみると、数秒後に次のタイル更新が表示されます (左側はワイドのタイル、右側は正方形のプレビュー タイルを 2 つ組み合わせたもの)。
同じものを NotificationsExtensions ライブラリを使って作成してみましょう。最初に、目的の Web サイト用のライブラリを構築する必要があります。次の手順に従ってください。
- 「アプリのタイルおよびバッジのサンプル」(英語) にアクセスし、このプロジェクトの NotificationsExtensions フォルダーをコピーします (このライブラリは Visual Studio から直接インストールすることもできます。プロジェクトを右クリックし、[NuGet パッケージの管理] をクリックして、NotificationsExtensions.WinRT を検索します。ただし、この方法ではライブラリが既存のアプリ プロジェクトに読み込まれます。この記事ではスタンドアロンの DLL を作成する必要があります)。
- Visual Studio Express for Windows で NotificationsExtensions.csproj ファイルを開きます。
- ソリューション エクスプローラーで、NotificationsExtensions プロジェクトを右クリックし、[プロパティ] をクリックして、次のように変更します。
- [アプリケーション] 設定で [出力の種類] を [クラス ライブラリ] (.dll) に変更します。ライブラリを ASP.NET サイトで使用するためには、この指定が必要です。
- [ビルド] 設定で、[構成] を [すべての構成] に変更し、[条件付きコンパイル シンボル] を「NETFX_CORE; WINRT_NOT_PRESENT」に変更して、このページの下の方にある [XML ドキュメント ファイル] チェック ボックスがオンになっていることを確認します。"WINRT_NOT_PRESENT" フラグを指定すると、WinRT なしでライブラリをコンパイルできます。
- デバッグまたはリリース ターゲットを選択して、NotificationExtensions プロジェクトを右クリックし、[ビルド] をクリックします。
これで DLL と関連ファイルがこのプロジェクトのフォルダーに生成されます。次は、これを Web サイト プロジェクトに組み込む必要があります。
- サイトにまだ Bin フォルダーがない場合は、Visual Studio Express for Web で Web サイト プロジェクトを右クリックし、[追加]、[ASP.NET フォルダーの追加]、[Bin] の順にクリックして追加します。
- Bin フォルダーを右クリックして、[参照の追加] をクリックします。[参照の追加] ダイアログ ボックスで、NotificationsExtensions プロジェクトの bin\Debug または bin\Release フォルダーに移動し、そのフォルダーにある DLL を選択します。
Visual Studio Ultimate を使っている場合はどちらの種類のプロジェクトも処理できるため、必要に応じて、NotificationsExtensions プロジェクトを Web サイト ソリューションに追加できます。ただし、くれぐれもプロジェクトのソース コードを Web サーバーに配置しないように注意してください。
ブラウザーでローカルに実行するサイトを構築する場合は (次の「サービスのデバッグ」のセクションを参照)、System.Runtime への参照の追加に関するエラーが発生する可能性があります。これを修正するには、web.config ファイルを開いて、compilation 要素を次のように変更します。
<compilation debug="true" targetFramework="4.0"> <assemblies> <add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> </assemblies> </compilation>
以上の構成がすべて完了すると、前のハード コーディングされたサンプルと同じ出力を生成するページ (DefaultNE.aspx) は次のようになります。
<?xml version="1.0" encoding="utf-8" ?> <%@ Page Language="C#" %> <script runat="server"> 1:
2: public string GenerateTileXML()
3: {
4: // Construct the square template
5: NotificationsExtensions.TileContent.ITileSquarePeekImageAndText02 squareTile =
6: NotificationsExtensions.TileContent.TileContentFactory.CreateTileSquarePeekImageAndText02();
7: squareTile.Branding = NotificationsExtensions.TileContent.TileBranding.None;
8: squareTile.Image.Src = "https://www.kraigbrockschmidt.com/images/Liam07.png";
9: squareTile.TextHeading.Text = "Liam--";
10: squareTile.TextBodyWrap.Text = "Giddy on the day he learned to sit up!";
11:
12: // Construct the wide template
13: NotificationsExtensions.TileContent.ITileWideSmallImageAndText04 wideTile =
14: NotificationsExtensions.TileContent.TileContentFactory.CreateTileWideSmallImageAndText04();
15: wideTile.Branding = NotificationsExtensions.TileContent.TileBranding.None;
16: wideTile.Image.Src = "https://www.kraigbrockschmidt.com/images/Liam08.png";
17: wideTile.TextHeading.Text = "This is Liam";
18: wideTile.TextBodyWrap.Text = "Exploring the great outdoors!";
19:
20: // Attach the square template to the notification
21: wideTile.SquareContent = squareTile;
22: wideTile.Lang = "en-US";
23:
24: // The wideTile object is an XMLDOM object, suitable for issuing tile updates
25: // directly. In this case we just want the XML text.
26: return wideTile.ToString();
27: }
</script>
<%1: = GenerateTileXML()
%>
このサービスには https://programmingwin8-js-ch13-hellotiles.azurewebsites.net/DefaultNE.aspx (英語) でアクセスできます。返される XML は基本的に前と同じで、わずかな違いしかありません。この URI を「プッシュおよび定期通知のクライアント側のサンプル」のシナリオ 4 にコピーした場合も、前と同じタイル更新が生成されます。
サービスのデバッグ
タイル更新またはバッジ更新が正常に生成される場合は、当然、サービスの応答に含まれる XML のフォーマットは適切であると考えられます。フォーマットが適切でない XML は、Windows によって拒否されます。NotificationsExtensions ライブラリのメリットはここにあります。NotificationsExtensions ライブラリを使うと、サービスの作成中のエラーを削減できます。
しかし、サービス自体が適切に動かない場合はどうでしょうか。サービスが要求をどのように処理して応答を生成しているかを診断し、デバッグするにはどうしたらよいでしょうか。
実は、上の ASP.NET サービスのコードを初めて試したとき、XML 応答の先頭に改行があったために、更新が表示されませんでした。<?xml ?> ヘッダーが <%@ Page %> ディレクティブの後ではなくファイルの 1 行目に指定されていて、余分な改行文字がないのは、そのためです。
サービス コードをステップ実行し、1 行ずつデバッグすることが必要になる状況はたくさんあります。特に、データベースを照会してクエリ結果を処理する場合はなおさらです。
これを行うには、開発用コンピューターで localhost を使う方法が役に立ちます。そうすれば、SDK サンプルなどのクライアント テスト コードを実行しながら、同時にサービスをローカルで実行してデバッグできます。
localhost を使うということは、インターネット インフォメーション サービスや Apache などのローカル Web サーバーを実行することになります。Windows に組み込まれている IIS を有効にするには、コントロール パネルの [Windows の機能の有効化または無効化] を開きます。以下の図のように、トップ レベルにある [インターネット インフォメーション サービス] チェック ボックスをオンにします。
IIS がインストールされると、https://localhost/ というアドレスに対応するローカル サイトが c:\inetpub\wwwroot フォルダーに作成されます。前のセクションで作成した PHP ページなどをここに置くと、クライアント サンプルで https://localhost/dayofmonthservice.php などの URI を使用できるようになります。
IIS で PHP を使うには、マイクロソフトの Web Platform Installer (英語) を使って PHP をインストールしないと、サーバー側のコードが適切に実行されない可能性があります。PHP をインストールしたら、ブラウザーにローカル PHP の URI を入力してみましょう。"ハンドラー PHP53_via_FastCGI のモジュール リストにあるモジュール <モジュール名> が正しくありません" というエラー メッセージが表示された場合は (実に役立つメッセージですね)、先ほどの [Windows の機能の有効化または無効化] ダイアログ ボックスに戻り、[インターネット インフォメーション サービス]、[World Wide Web サービス]、[アプリケーション開発機能] の順に展開し、[CGI] チェック ボックスをオンにして、[OK] をクリックします。CGI エンジンがインストールされたら、PHP ページが動作するようになります。
localhost が配置されると、ローカルのコンピューターで Visual Studio Express for Web または Visual Studio Ultimate を使ってサービスをデバッグできます。また、Visual Studio Express for Web と Visual Studio Express for Windows を併用することで、クライアントとサーバーのコードを同時にデバッグできます。
Visual Studio (for Web) デバッガーから実行されたサービスや Web サイトは、ブラウザーで "https://localhost:<ポート>/" のような URL を使って実行されます。"<ポート>" は、そのプロジェクトにランダムに割り当てられます。たとえば、前のセクションの DefaultNE.aspx ページを Visual Studio Express for Web で実行すると、このページは Internet Explorer で https://localhost:52568/HelloTiles/DefaultNE.aspx という URI を使って開かれます。このページのコードにブレークポイントを設定していた場合、デバッガーは直ちにそのブレークポイントで停止します。
ブレークポイントは、同じ localhost URI をクライアント コードで使って要求を開始した場合にもヒットします。したがって、たとえば、「プッシュおよび定期通知のクライアント側のサンプル」を Visual Studio Express for Windows で実行し、URI をシナリオ 4 にコピーした場合、Windows から要求が発行されるとすぐに、Visual Studio Express for Web のデバッガーで実行されているサービスは停止します。ここからコードをステップ実行し (さいわい Windows ではこのような気長な処理が可能です)、正しい応答が生成されるかどうかを確認できます。正しい応答が生成されない場合は、コードを修正し、localhost でサービスを再起動します。
サービスが意図したとおりに動作することを確認できたら、運用中の Web ホスト (またはステージング環境) にサービスをアップロードし、最後の運用テストを実施します。
この方法で localhost を使う場合、デバッガーでクライアント コードを実行する必要はありません。それでもデバッガーでクライアント コードを実行する場合は、localhost が正しく機能するように、Visual Studio のオプションの 1 つをオンにする必要があります。既定でこのオプションは有効にされていますが、変更が必要な場合は、プロジェクトのプロパティで [デバッグ] の [ローカル ネットワーク ループバックの許可] を変更してください。
外部ソースのデータ
定期通知サービスでは、サービス自身のデータベースを照会するだけでなく、他のサービスに要求を送信し、その応答としてデータを取得することもできます。ただし、このような要求は事実上非同期になるため、さまざまなエラー状態が発生しやすいのが欠点です。したがって、このような要求を使う場合は、サービスの実装がかなり複雑になる可能性があります。
実装をシンプルにするには、クライアント API の制御により、Windows は 30 分以上に 1 回しか要求を発行しないという事実を利用できます。つまり、時間は十分にあるので、その間に他のサーバー側プロセスから外部への要求を発行すれば、気象警報、ランキング、RSS フィード、その他 Web API が用意されている情報ならほとんど何でも監視できます。照会した結果は各プロセスによってデータベースに格納され、定期通知サービスが次の要求を受信したときに、(同期的に) これらの結果を照会できる状態になります。
実際、さまざまなエージェントから同じデータベースを更新することができます。たとえば、ユーザーが Web サイトを通してデータを入力する場合もあれば、ユーザーが携帯電話アプリを使って自分のアクティビティを管理し、その結果が自動的にデータベースにアップロードされる場合もあります。また、同じアプリを使っている友人によって、各自のデバイスからデータベースが更新される場合もあります。
このような構成を表したのが下の図です。データベース サーバーがバックエンド状態のセントラル ストアとなり、定期通知サービスは、単にその状態を利用する役割のみを果たします。
定期更新サービスでの Windows Azure モバイル サービスの使用
ライブ タイルやその他の通知をサポートするバックエンド サービスについて理解し、作成し始めたら、ぜひ Windows Azure モバイル サービス (英語)、略して AMS を使ってみてください。AMS を使うと、このシリーズのパート 3 で説明するプッシュ通知が格段にシンプルになるだけでなく、定期更新サービスを複数の方法でサポートできます。
- モバイル サービスでは、定期的に他のサービスに要求を送り、結果をデータベースに格納するバックグラウンド ジョブをスケジュールできます。この例として、「モバイル サービスでの定期的なジョブのスケジュール」(英語) では、Twitter からのツイートを取得するジョブを紹介しています。
- SQL Server データベースを AMS (または Windows Azure の他のサービス) に作成すると、このデータベースは Web でホストされている他の SQL Server データベースと同様にアクセスできるため、Web サイトや他のサービス (PHP で作成されたサイトやサービスを含む) から使用できます。
- AMS では、モバイル サービス SDK (英語) を使って、非常に簡単にクライアント アプリからデータベースにレコードを挿入できます。
- モバイル サービスとは別に、Windows Azure では Node.js、Python、Java、PHP、.NET など、さまざまな言語で作成されたサーバー側プロセスをホストできます。
将来的には、"サービス操作" という新機能にも注目してください。これにより、Azure モバイル サービスでは、定期通知サービスも含めて任意の http エンドポイントを作成できるようになります。
Windows Azure の詳細については、https://www.windowsazure.com を参照してください。また、Channel 9 の「Windows Azure モバイル サービスのチュートリアル」(英語) の入門用ビデオも参照してください。
これで定期通知サービスの作成方法を確認できたので、次はプッシュ通知についてお話しする予定です。プッシュ通知は、定期通知よりも頻繁に更新を発行する場合に必要となるもので、基本的にオンデマンドで発行されます ("プッシュ" 通知と呼ばれるのはこのためです)。このシリーズのパート 3 では、プッシュ通知というトピックを取り上げると共に、Azure モバイル サービスについてもさらに詳しく紹介します。
Kraig Brockschmidt
- Windows エコシステム担当チーム、プログラム マネージャー