かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Azure Mobile AppsでUWPを作ってみよう

食わず嫌いしてるMobile Appsですがここらへんで触ってみようと思います。バックエンドが簡単に作れるならそれにこしたことはないよね。ということで行ってみよう。

Mobile Apps Quickstartの作成

まず手始めにとっかかりをつかむには、Mobile Apps Quickstartというのを作るといいです。こいつはTodoアプリの完成形が出来上がってます。

f:id:okazuki:20160907194448p:plain

下のような感じで適当に作ります。

f:id:okazuki:20160907194822p:plain

そうすると、以下のセットが出来上がります。

f:id:okazuki:20160907202118p:plain

プロジェクトのダウンロードと実行

AppServiceを選んで、Quickstartを選ぶと、様々なプラットフォームのプロジェクトのひな型がDLできるようになっています。今回はUWPでいきたいのでWindows(C#)を選びます。

f:id:okazuki:20160907202449p:plain

Quickstartは、SQLiteを使ってるみたいですね。後で、SQL Databaseに変えてね的なメッセージが出てます。しばらく待つと、大体緑になりますので、Downloadボタンを押します。ダウンロードしたらプロパティからブロックを解除して展開します。

x86をターゲットに変えて何も考えずに実行してみましょう。 以下のように、TODOアプリが立ち上がります。動きますね。

f:id:okazuki:20160907202919p:plain

データの確認

Azureのポータルで、ドキュメントでは簡単テーブルと残念翻訳されてるEasy Tableを選びます。するとテーブルの中身を見ることが出来ます。先ほど実行したデータが入ってることが確認できます。

f:id:okazuki:20160907203151p:plain

認証をつけてみよう

Twitterで認証かけてみましょう。Twitterの開発者ポータルに行ってアプリを登録します。

Twitter Developers

ここの下のほうにManage Your Appsがあるので、そこからアプリを登録します。登録時に入力するコールバックとウェブサイトですが、以下のドキュメントにあるようにhttps://アプリ名.azurewebsites.net/.auth/login/twitter/callbackを指定します。今回は、okazukitodoという名前で私は作ったのでhttps://okazukitodo.azurewebsites.net/.auth/login/twitter/callbackになります。

azure.microsoft.com

DetailsタブとKeys And Access Tokensタブに必要な情報があるので、閉じずにキープしておきます。

Easy Tabletodoitemテーブルを選んで上のほうにあるChange permissionsを選択します。Insert, Update, Delete, Read, Undeleteのpermissionが全部匿名ユーザーに対して許すようになってるので、これをAuthenticated access onlyに変更して認証が必要なようにします。Saveを押すのを忘れずに。

f:id:okazuki:20160907204608p:plain

次にアプリ全体に認証をかけます。App Serviceを選んでAuthentication / Authroizationを選択します。App Service AuthenticationOffになってるのでOnに変更します。 そして、Twitterを選択します。先ほどのTwitterのページから取得できるAPI Key(Cosumer Keyともいう)とAPI Secret(Cosumer Secretともいう)をコピペします。

f:id:okazuki:20160907204952p:plain

入力したらSaveを忘れずにやっておきます。

この時点でアプリを実行すると認証エラーが起きるようになります。

f:id:okazuki:20160907205152p:plain

そして、テーブル自体にも認証が必要なようにします。Easy Tabletodoitemを選択して、Edit scriptを選択します。ブラウザでスクリプトが編集できるので、以下の1行を13行目あたりに追加しておきます。

table.access = 'authenticated';

認証処理を追加しましょう。MainPage.xamlにアプリバーを追加して、そこにログインボタンを置くようにししてみましょう。

<Page.BottomAppBar>
    <CommandBar>
        <AppBarButton Label="SignIn"
                      Icon="Contact" 
                      Click="SignInButton_Click"/>
    </CommandBar>
</Page.BottomAppBar>

そして、コードビハインドで以下のようなコードを書きます。

private MobileServiceUser User { get; set; }

private async void SignInButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        this.User = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);
        await new MessageDialog($"サインインに成功しました: {this.User.UserId}").ShowAsync();
    }
    catch(InvalidOperationException)
    {
        await new MessageDialog("サインインに失敗しました").ShowAsync();
    }
}

実行してアプリバーのボタンを押すと以下のような画面が出てきます。

f:id:okazuki:20160907210404p:plain

サインインに成功すると、ちょっと残念なユーザー名が表示されます。

f:id:okazuki:20160907210502p:plain

そうすると、アプリが使えるようになります。

f:id:okazuki:20160907210604p:plain

毎回サインインするのは怠いので、認証トークンを保存しておくようにしましょう。サインインのボタンのクリック処理を以下のようにします。

private async void SignInButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        this.User = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);

        // これを追加
        var vault = new PasswordVault();
        vault.Add(new PasswordCredential("Twitter", this.User.UserId, this.User.MobileServiceAuthenticationToken)); 

        await new MessageDialog($"サインインに成功しました: {this.User.UserId}").ShowAsync();
    }
    catch(InvalidOperationException)
    {
        await new MessageDialog("サインインに失敗しました").ShowAsync();
    }
}

そして、MainPageOnNavigatedToあたりで復元処理を追加します。Userを作ってCurrentUserにセットする感じです。

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var vault = new PasswordVault();
    try
    {
        var c = vault.FindAllByResource("Twitter").FirstOrDefault();
        if (c != null)
        {
            this.User = new MobileServiceUser(c.UserName);
            c.RetrievePassword();
            this.User.MobileServiceAuthenticationToken = c.Password;
            App.MobileService.CurrentUser = this.User;
        }
    }
    catch
    {
    }

    //await InitLocalStoreAsync(); // offline sync
    ButtonRefresh_Click(this, null);
}

これで、二度目の実行からは無事ログインしなくてもデータが読み込まれます。

次はサーバーサイドの処理を色々見ていけたらなと思います。JavaScript嫌いだけど…。