かずきのBlog@hatena

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

Azure Mobile AppsでUWPを作ってみよう「プッシュ通知編」

過去記事

あらすじ

オフライン同期まで出来たので次はプッシュですよ、プッシュ。

通知ハブの作成

Mobile Appsでプッシュ通知を行うにはNotification Hubを使います。 Mobile Appsを選んだ状態でMOBILEPushを選んでNotification Hubを作っていきます。Notification Hubの名前と、Namespaceの名前をつけます。

作るとこんな感じになります。

f:id:okazuki:20160910024150p:plain

プッシュ通知を送るようにサーバーの処理を変える

どんなタイミングで送ってもいいのですが、TodoItemテーブルにデータが追加されたときにプッシュ通知を送るようにしてみたいと思います。

TodoItem.tsで以下のようにinsert時に処理を挟み込むことが出来ます。

import * as azureMobileApps from 'azure-mobile-apps';

let table = azureMobileApps.table();

// 動的生成しない
table.dynamicSchema = false;
// テーブルの定義
table.columns = {
    text: "string",
    complete: "boolean"
};

table.insert(context => {
    return context.execute()
        .then(r => {
            // Pushが構成されてたら
            if (context.push) {
                // messageParam(任意の名前でOK)に追加されたデータのテキストを突っ込んでプッシュ通知
                context.push.send(null, { messageParam: context.item.text }, error => {})
            }
            return r;
        });
});

module.exports = table;

これでサーバーサイドは完成です。

クライアント側の構成

クライアント側でプッシュ通知を受け取るには、ストアとアプリを紐づけないといけません。プロジェクトの右クリックメニューからStoreAssociate app with the store...を選びます。

デベロッパーセンターでアプリ名を登録してたら、それを選択して、登録してなかったら画面下のほうのReserve a new app name:でアプリ名を予約して紐づけます。

f:id:okazuki:20160910024836p:plain

デベロッパーセンターのダッシュボードを開いて、先ほど予約した名前のアプリを選択します。選択した先のページでプッシュ通知を探します。そこのはじめにというリンクをクリックします。

f:id:okazuki:20160910025211p:plain

そしてLive サービス サイトのリンクをクリックします。

f:id:okazuki:20160910025320p:plain

その先のページでアプリケーションシークレットパッケージ SIDが記載されているのでメモっておきます。

メモったアプリケーションシークレットとパッケージ SIDをMobile Appsに紐づけます。AzureのポータルでMobile Appsを選択して、PushWindows(WNS)を選びます。Package SIDSecret Keyの入力項目があるので、先ほど入手したパッケージ SIDアプリケーションシークレットを入れます。

f:id:okazuki:20160910025707p:plain

正しい値を入れると、Saveが成功します。コピペミスをすると(スペースが入ったり)エラーになります。

そして、アプリの起動時OnLaunchedメソッドのFrameの生成処理前くらいに以下のコードを追加します。OnNavigatedToメソッドでやると何故かCreatePushNotificationChannelForApplicationAsyncが結果を返さなかったので、アプリ起動時にやるのがいいのでしょう。templateBody変数が、表示するトーストの中身になります$(....)で、サーバーサイドで指定した値の埋め込みが指定できます。今回の例ではmessageParamになります。

// Property
public MobileServiceClient Client { get; } = new MobileServiceClient("http://customokazukitodoapp.azurewebsites.net");

// OnLaunched
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var templateBody = @"
    <toast>
        <visual>
            <binding template=""ToastText01"">
                <text id=""1"">$(messageParam)</text>
            </binding>
        </visual>
    </toast>";
var headers = new JObject();
headers["X-WNS-Type"] = "wns/toast";
var templates = new JObject();
templates["genericMessage"] = new JObject
{
    { "body", templateBody },
    { "headers", headers },
};
await this.Client.GetPush().RegisterAsync(channel.Uri, templates);

MainPage.xaml.csで生成してたMobileServiceClientをAppに持ってきました。それに伴い、MainPage.xaml.csでそれを参照するようにちょろっと書き換えます。

private MobileServiceClient Client { get; } = ((App)App.Current).Client;

これで完成です。実行して何かデータを追加すると以下のようにプッシュ通知が飛んできてトーストが出てきます。

リアルタイムに降ってくるわけではないので、気長に待ってると以下のようにデータを登録したあとに、その内容がプッシュ通知されます。

f:id:okazuki:20160910030649p:plain