Windows ストアアプリ - バックエンドサービスの作成例 (1) (C# / XAML 編)

皆様、こんにちは!

すっかり久しぶりになってしまったこのBlog執筆、かなりネタも溜まりまくっているので、一人Advent Calender的に連日書いていきます。

早速本日は、大作w?のMobile Services を使った、Windows ストアアプリのバックエンドサービスの作成です。

それでは、さっそく中身に入りましょう。

概要

Windows Azure Mobile Services (以下、Mobile Services)には、データの保存、プッシュ通知、ユーザー認証を実現するための便利な一連の機能が提供されています。特に、Mobile ServicesのServer Scriptを使用すると、データの保存時にアプリケーションのユーザーにプッシュ通知を送る機能を簡単に実装することができます。また、ユーザー認証では、Microsoft AccountにのみならずFacebook ID、Twitter IDでも認証が可能です。

このラボでは、Contoso Cookbook を拡張して、アプリケーションを利用しているユーザーがお気に入り登録しているレシピが、アプリケーションのタイルにプッシュ通知されるようにします。また、これらの機能を実現するために、Windows Azure Mobile Servicesを利用して、データの保存、プッシュ通知、ユーザー認証を実現する方法を学習します。

image

演習 1: データを保存する

Contoso Cookbookのタイルにプッシュ通知を行う前に、レシピに対して、お気に入り登録ができるコマンドを追加します。Mobile Servicesを利用すると、データをバックエンドサービスに保存しプッシュ通知を行う機能を簡単に実装することが出来ます。

タスク 1 – Mobile Servicesの設定とテーブルの作成

新しいMobile Serviceを作成し、既存のアプリケーションとの接続およびこの後のラボで使用するテーブルの作成を行います。その後、アイテム詳細ページのアプリバーにお気に入りボタンを追加し、Mobile Service上のテーブルに当該レシピの情報を保存します。

1. 新しいMobile Servicesを作成します。管理ポータル左下の”新規”ボタンをクリックし、コンピューティングモバイルサービス作成、と進みます。

image

2. 各種設定ウィンドウが開かれます。URLは適当なものを入力し、データベースは”新しいSQLデータベースインスタンスを作成する”を選択します。

image

注:地域は、必ず合衆国西部合衆国東部にしておいてください。そうしないとMobile Services がPreview 期間中は、10個まで無償というサービスが適用されません。

 

3. 次の画面では、サーバーを新しいSQL データベースサーバーを選択し、ログイン名パスワードを新規に設定してください(“データベースの詳細設定を構成します”チェックボックスはチェックしません

image

注:地域は、必ず合衆国西部合衆国東部で、先ほどMobile Services を作成したのと同じ地域にしておいてください。そうしないとMobile Services がPreview 期間中は、10個まで無償というサービスが適用されません。また無駄なトラフィックが増えてしまい課金も増加する可能性があります。

4. Mobile Serviceが作成されます。

image

5. Windows Azure の管理ポータル上でクイックスタートタブに切り替えます。

image

6. 既存の Windows ストア アプリに接続するを展開します。アプリへ接続する のLANGUAGE

C# に変更し、表示されたコードをコピーします。

image

7. ダウンロードした、ContosoCookbookプロジェクト(どれでも良いですがApp Barが実装済みのものが良いでしょう)を、Visual Studio で開きます。

App.xaml.cs ファイルを開き、最初に参照設定で、参照マネージャーから、WindowsAzure Mobile Services Managed Clientを追加します(Mobile Services SDKをインストール済みであればここに表示されます。未インストールであれば、先ほどの Windows Azureのクイックスタートのページの中にあるリンクからダウンロードしてインストールしてください)。

image

続いて、App.xal.csに、下記のUsing 句を追加します。

C#

 using Microsoft.WindowsAzure.MobileServices;

 

App.xal.csで以下のコードを探します。

C#

 namespace ContosoCookbook
 {
     /// <summary>
     /// 既定の Application クラスを補完するアプリケーション固有の動作を提供します。
     /// </summary>
     sealed partial class App : Application
     {

探したコードの後、コンストラクターの直前に、以下の部分を追加します。これで、このWindows ストアアプリにMobile Services が接続可能となります。

C#

 public static MobileServiceClient MobileService = new MobileServiceClient(
 "https://[作成されたMobile Services の名前].azure-mobile.net/","[生成されたキー]"

続いて、このラボで使用するテーブルをMobile Service上に作成します。これを使って、Mobile Services上にデータを保存します。Windows Azure の管理ポータル上でデータタブに切り替え、中央下にある作成ボタンをクリックします。テーブル名Favoritesと入力しテーブルを作成してください。同様にChannelという名前のテーブルも作成します。こちらは後述するプッシュ通知に使います。

タスク 2 – アプリバーにお気に入りボタンを追加しデータを保存する

最初に、アイテム詳細ページのアプリバーにお気に入りボタンを追加します。その後、追加ボタンを押した際、Mobile Service上のFavoritesテーブルに当該レシピの情報を保存します。

1. 既に追加されているアプリバーに、お気に入りボタンを追加しましょう。ソリューションエクスプローラで、ItemDetailPage.xamlファイルを開き、XAML ビューに切り替えます。ドキュメントアウトラインウィンドウで、BottomAppBar をハイライトします。すると、Page.BottomAppBar が表示されます。

2. XAMLのBottomAppBar の中に、下記の黄色にハイライト下部分を追加し、ボタンAddを追加します。これらに指定しているスタイルも、デフォルトでは有効になっていないので、Commonフォルダ内にある、StandardStyles.xaml を編集し、追加します。

XAML

 <Page.BottomAppBar>
        <AppBar x:Name="PageAppBar" Padding="10,0,10,0">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50*"/>
                    <ColumnDefinition Width="50*"/>
                </Grid.ColumnDefinitions>
                <StackPanel x:Name="LeftCommands" 
 rientation="Horizontal"
                            Grid.Column="0" HorizontalAlignment="Left">
                    <Button x:Name="BragButton" 
                            HorizontalAlignment="Left" 
                            Style="{StaticResource 
 ragAppBarButtonStyle}"
                            Click="OnBragButtonClicked" />
                    <Button x:Name="AddtoFavorites" 
                            HorizontalAlignment="Left" 
                            Style="{StaticResource 
 ddAppBarButtonStyle}"/>
                <StackPanel x:Name="RightCommands" 
                            Orientation="Horizontal" Grid.Column="1"
                            HorizontalAlignment="Right">
                </StackPanel>
            </Grid>
        </AppBar>
    </Page.BottomAppBar>

 

3. XAML デザインモードにし、AddtoFavoritesボタンをアプリバーに追加(手順は割愛します)し、クリックイベントを追加します。

ItemDetailPage.xaml.csファイルを開き、public sealed partial class ItemDetailPage : ContosoCookbook.Common.LayoutAwarePage の直下に下記を追加します。

 private MobileServiceCollectionView<Favorites> favitems = null;
 private IMobileServiceTable<Favorites> favoriteTables = App.MobileService.GetTable<Favorites>();

4. SaveState メソッドを変更します。

C#

 private async void InsertFavoriteItems(FavoriteItems favs)
         protected override void SaveState(Dictionary<String, Object> 
             pageState)
         {
             //var selectedItem = (RecipeDataItem)this.flipView.SelectedItem;
             // ポートレイトへの対応(スナップは考えない)
             RecipeDataItem selectedItem = null;
             if (this.flipView.Visibility == 
                 Windows.UI.Xaml.Visibility.Visible)
                     selectedItem = (RecipeDataItem)this.flipView.SelectedItem;
             else
                     selectedItem = 
                         (RecipeDataItem)this.portraitFlipView.SelectedItem;
  
             pageState["SelectedItem"] = selectedItem.UniqueId;
             // Deregister the DataRequested event handler
             DataTransferManager.GetForCurrentView().DataRequested -= OnDataRequested;
 }

 

5. 以下のコードを追加します。このコードにより、AppBarに追加した、お気に入りボタン(AddtoFavorites)のClick イベントをハンドルし、Mobile Services上にデータを保存します。実体は別のメソッド(InsertFavoriteItems)に書きます。

C#

 private void AddtoFavorites_Click(object sender, RoutedEventArgs e)
 {
             var selectedItem = 
                 (RecipeDataItem)this.flipView.SelectedItem;
  
             var favItem = new Favorites { Text = selectedItem.Title, 
                 UserID = “testuser”};
  
                     InsertFavoriteItems(favItem);
 }
 private async void InsertFavoriteItems(Favorites favs)
 {
     await favoriteTables.InsertAsync(favs);
     favitems.Add(favs);
 }

タスク 3 – 結果をテストする

アプリバーの動作を確認します。F5 キーを押してアプリを実行します。

レシピを選択し、アイテム詳細ページに移動します。Windows キーを押しながら Z キーを押して、アプリ バーを表示します。アプリ バーの( [AddtoFavorites] コマンドが割り当てられた)Addボタンをクリックします。

screenshot_12122012_172213

Mobile Servicesの管理ポータルからFavoritesテーブルを選択し、データが追加されていることを確認します。

image

Windows キーを押しながら D キーを押して Visual Studio に戻り 、 [デバッグ] メニューの [デバッグの停止] をクリックします。

演習 2 プッシュ通知を実装する

ユーザーが選択したお気に入りのレシピを、バックエンドサービスに保存する仕組みは実装できました。今度は、Mobile ServicesのPush通知機能を利用し、アプリケーションのユーザーが選択したお気に入りレシピを、タイルに通知されるようにします。Mobile Servicesには、データの保存や読み込み時に実行されるServer Scriptという仕組みが用意されています。この仕組みを利用して、各ユーザーからお気に入りのレシピが送られてくると、それをすべてのユーザーのタイルに通知する仕組みを実装します。

タスク 1 – Push通知実装の準備

Mobile ServicesからPush通知を送信するためには、アプリケーションごとのClient secretおよびSIDを取得し、Mobile Servicesに登録する必要が有ります。

この設定は、アプリを開発者ダッシュボードに申請した上で行う必要が有ります。

1. Visual Studio に戻り、プロジェクトを右クリックして、ストアメニューから、アプリケーションをストアと関連付ける、 を選択します。

image

2. 下記のようなダイアログボックスが出るので、開発者アカウントでログインします。

image

3. すると、ストアのダッシュボードのページへと誘導されますので、アプリに一意な名前を付けて保存します(ここではCookbookCS としています)。

image

4. 保存したら、左側の高度な機能というリンクをクリックすると、そこに、プッシュ通知とLive Connect サービスの情報というリンクがあるので、これをクリックします。

image

5. ”アプリでWNS を利用してプッシュ通知を行う場合は、次の点を確認してください”の下にある、サービスの認証、のリンクをクリックします。

image

6. パッケージセキュリティID SID およびクライアントシークレットが生成されていますので、内容を確認します。

image

7. モバイルサービスのポータルのプッシュのタブの中の対応するフィールドに、それぞれコピーして貼り付け、保存します。

image

8. 演習1タスク1の5で追加したコードの後に、以下のステートメントを追加します。ここではアプリケーションのChannel Uriを取得しそれをMobile ServicesのChannelテーブルに追加しています。App.xaml のOnLaunched メソッドを、async に変更してから、一番下に下記のブロックを挿入します。

C#

 var ch = 
     await PushNotificationChannelManager.
         CreatePushNotificationChannelForApplicationAsync();
     await MobileService.GetTable<Channel>().InsertAsync(new Channel() { Uri = ch.Uri });

9. 同時にChannel クラスもApp.xamlの最後に追加しておきます。

C#

 public class Channel
 {
     public int Id { get; set; }
     public string Uri { get; set; }
 }

 

10. 最後に、ItemDetailPage.xaml.csに戻り、OnNavigatedToと、GetFavoritesメソッドを、下記のように追加します。

C#

 protected async override void OnNavigatedTo(NavigationEventArgs e)
 {
  // このタイミングでデータを取得する場合、もう一度自分で呼び出します。
             var item = RecipeDataSource.GetItem((String)e.Parameter);
   // RecipeDataItemが取得できれば、Titleなどへアクセスできます。
             await Authenticate();
  
             GetFavorites();
  
             // LayoutAwarePageのOnNavigatedTo を呼び出します
             base.OnNavigatedTo(e);
         }
  
         void GetFavorites()
         {
             favitems = favoriteTables
                         .Where(item => item.Complete == false)
                         .ToCollectionView();
         }

 

タスク 2 – Server Scriptの編集

Server Scriptを利用すると、Mobile Services上に作られたテーブルに対する操作を行う際に、特定の処理を行うことができます。この演習では、Server Scriptの機能を使用し、データのバリデーションとプッシュ通知の機能を実装します。具体的には、Channelテーブルに新しいURIが追加される際、既にテーブルにないURIの場合のみデータを追加します。また、Favoritesテーブルにデータが追加された際には、Channelテーブルに保存されているURIに対してプッシュ通知を送信します。

1. Mobile Servicesの管理ポータルからDATAタブを開き、Channelテーブルを選択します。ScriptタブをクリックしInsertを選択、表示されるコードを下記に書き換えます。

JavaScript

 function insert(item, user, request){
   var channelTable = tables.getTable(“Channel”);
   channelTable
     .where({ uri: item.uri })
     .read({ success: insertChannelIfNotFound });
  
   function insertChannelIfNotFound(existingChannels){
     if(existingChannels.length > 0){
       request.respond(200, existingChannels[0]);
     } else {
       request.execute();
     }
     request.execute();
   }
 }

今度はFavoritesテーブルを選択し、同じように”スクリプト”タブをクリックして、ドロップダウンメニューから”挿入”を選択、表示されるコードを下記に書き換えます。

JavaScript

 function insert(item, user, request) {
     request.execute({
         success: function(){
             request.respond();
             sendNotifications();
         }
     });
 }
  
 function sendNotifications(item){
     var channelTable = tables.getTable("Channel");
             channelTable.read({
                 success: function(channels){
                     channels.forEach(function(channel){
                         push.wns.sendTileWideText04(channel.uri, {
                             text1: item.text,
                     },
                     {
                         success: function(pushResponse){
                             console.log( "Sent push:", pushResponse);
                     }
                 });
             });
         }
      })
 }

タスク 3 – 結果をテストする

プッシュ通知の動作を確認します。

F5 キーを押してアプリを実行します。レシピを選択し、アイテム詳細ページに移動します。

Windows キーを押しながら Z キーを押して、アプリ バーを表示します。

アプリ バーの [Favorites] コマンドをクリックします。

Mobile Servicesの管理ポータルより、”ログ”タブを選択し、プッシュ通知のログが残っている事を確認します。

※下図はServer Script でトーストにした場合の実行例

image

演習 3 : ユーザー認証を実装する

これで、Contoso Cookbook のタイルには、ユーザーがお気に入り登録したレシピの情報がプッシュ通知されるようになりました。この演習では、ユーザーも追加します。アプリケーションを起動時にユーザーの認証を行い、レシピをお気に入り登録際に、ユーザーのIDも保存するようにします。

タスク 1 – ユーザー認証のための設定を行う

Windows Azure Mobile Servicesでは、Microsoft 、Facebook、Twitter, GoogleのいずれかのIDを用いてユーザー認証を行うことができます。認証を実装するために必要な情報を、Mobile Servicesに登録後、起動時に認証を行う処理を追加します。

1. 管理ポータルのIDタブを開き、ユーザー認証で用いたいサービスの情報を入力します。ここではMicrosoft アカウントを使うやり方を示します。

image

2. Favoritesテーブルを操作する際、ユーザー認証が完了している事を条件とします。Favoritesテーブルの”データ”タブから、”アクセス許可”のタブを開き、すべての設定項目を ”認証されたユーザーのみ”に変更し、保存します。このまま Visual Studio でプロジェクトを実行すると、401 (Unauthorized) のエラーが発生します(予想通り)。

3. そこで、Visual Studioで、演習1タスク1の5で追加したコードの後に、以下のステートメントを追加します。ここではアプリケーションの起動時にユーザーの認証を促すダイアログを表示します。

C#

 private MobileServiceUser user;
 private async System.Threading.Tasks.Task Authenticate()
 {
     while (user == null)
     {
          string message;
          try
          {
              user = await App.MobileService
                         .LoginAsync(MobileServiceAuthenticationProvider.
                             MicrosoftAccount);
              message = string.Format("あなたは次のユーザーとしてログインしています - {0}", user.UserId);
                 }
                 catch (InvalidOperationException)
                 {
                     message = "ログインしてください。ログインが必要です。";
                 }
                     var dialog = new MessageDialog(message);
                     dialog.Commands.Add(new UICommand("OK"));
                     await dialog.ShowAsync();
             }
         }

 

4. AddtFavorites メソッドを下記のように修正します。

C#

 private void AddtoFavorites_Click(object sender, RoutedEventArgs e)
 {
       var selectedItem = RecipeDataItem)this.flipView.SelectedItem;
  
       var favItem = new Favorites
             { Text = selectedItem.Title, UserID = user.UserId };
  
       InsertFavoriteItems(favItem);
 }

 

5. F5 キーを押してアプリを実行し、ユーザーの認証が要求されることを確認します。(下記図はTwitterを使った例)

screenshot_12122012_172145

タスク 2 結果をテストする

F5 キーを押してアプリを実行します。

レシピを選択し、アイテム詳細ページに移動します。Windows キーを押しながら Z キーを押して、アプリ バーを表示します。アプリ バーの [Favorites] コマンドをクリックします。

screenshot_12122012_172213

Mobile Serviceの管理ポータルからFavoritesテーブルを選択し、ユーザーIDが付加されて、データが追加されていることを確認します。

image

 

Windows キーを押しながら D キーを押して Visual Studio に戻り 、 [デバッグ] メニューの [デバッグの停止] をクリックします。

まとめ

Window Azure Mobile Services を使うと、Windows ストアアプリに、迅速にバックエンドサービスの作成ができます。データベース接続、プッシュ通知(タイル、トースト等)、そして様々なIDを使った認証、等を迅速に実装でき、様々なアプリに応用可能ですので、ぜひ色々なアプリに付加するように試してみてください。

鈴木章太郎