酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Windows PhoneでAzure Mobile ServiceとNotification Hubを利用して2ステップでプッシュ通知機能を実装する #wpdev_jp

この記事は、「Windows Phone Advent Calendar 2014」の12日目の記事です。

Androidのマスコットといえばドロイド君ですが、Windows PhoneのマスコットといえばWindows Phoneマンです。これの現物を見たことがあるか、とあるシアトルルートから貰ったような気がするのですが、影も形もないので記憶違いなのかもしれません。

2011年から3回引っ越しをしているのでその際に紛失してしまったのかもしれません。いつもWindows Phoneマンの話をするときに探していますが見つかったことはありません。

f:id:ch3cooh393:20141205022744j:plain

Windows Foam 7 strikes back against Android mascot - MSPoweruser より

さて、本記事ではタイトルの通り、Windows Phoneアプリにプッシュ機能を追加する方法を紹介したいと思います。プッシュ機能を追加するためにはインフラ側(サーバー)を用意する必要があります。

サーバーを用意すること」と「プッシュ通知を送るシステムを用意すること」、その両方を準備するのはなかなか大変なので「Parse」をはじめ、沢山のサードパーティーのサービスがあります。Microsoft Azureというクラウドサービスを提供しているMicrosoft社でも「Azure Mobile Service」「Notification Hub(以下、通知ハブ)」といったサービスを提供しています。

通知ハブは、前述のParseと同様にマルチプラットフォームでプッシュ通知を管理することができるMicrosoft Azureのサービスのひとつです。

僕のMSCCの進捗はゼロですが、この記事を読んでいる方のMSCC用に開発中のアプリのひとアクセントになれば幸いです。

Windowsプッシュ通知サービスの簡単な仕組み

iPhoneやAndroidの浸透によって、当たり前のようにプッシュ通知が使われるようになりました。もちろんWindowsストアアプリとWindows Phoneアプリにもプッシュ通知を送るための機構が用意されています。この両者はユニバーサルアプリとして統合されたので、Windowsプッシュ通知サービス(以下、WNS)と呼ばれる共通の通知サービスが使用されます。

WNSの仕組みは下図の通りです。全体の流れとしてはWindowsストアアプリでも同じです(というかコード自体が同じ)。

f:id:ch3cooh393:20141212004505p:plain

上図を見て頂ければだいたいのプッシュ通知の流れが理解できると思います。Windowsストア/Windows Phoneアプリから「通知チャンネル」と呼ばれるデバイスとWNSとを関連付けたトークンを取得(①②)して、トークンを通知ハブに登録(③)する。

なんらかのイベントが発生したら通知ハブにプッシュ通知の送信を要求(④)すると、あとは通知ハブがWNSとのやり取りを肩代わり(⑤)してくれて、デバイスにプッシュ通知が送信(⑥)されるという流れです。

さて、Windows Phoneアプリにおけるプッシュ通知の仕組みが理解できたところで、実際にAzure Mobile Service(モバイルサービス)の通知ハブからWNSを経由して、Windows Phoneデバイスに対してプッシュ通知させてみましょう*1

あなたのアプリでプッシュ通知に対応させるためにやるべきこと

既にAzure Mobile Serviceを利用している場合、あなたのWindows Phoneアプリをプッシュ通知に対応させるには、下記のたった2ステップを実行するだけです*2

  • Visual Studioでプッシュ通知を受け取るための処理の追加
  • デバイスのチャンネルを通知ハブへ登録

たった2ステップだけであなたのWindows Phoneアプリがプッシュ通知機能が搭載されたWindows Phoneアプリになります。あとは通知ハブからWindows Phoneアプリ目掛けてプッシュを送りまくるだけです。

現在、Azure Mobile Serviceを利用していない方もたくさんいると思いますので、本記事では「Azure Mobile Serviceのサービスを新規作成する」と「通知ハブのデバッグからプッシュ通知を送る」についても触れたいと思います。

Azure Mobile Serviceのサービスを新規作成する

Microsoft Azureの管理ページにサインインします。管理ページのURLは以下の通りです。新ポータルの方にはモバイルサービスの操作はまだできません……。

管理ページに入ると、左下に[+新規]ボタンがあるのでクリックします。

f:id:ch3cooh393:20141211225246p:plain

ウィザードに従って、[コンピューティング]、[モバイルサービス]、[作成]の順にクリックしていきます。

f:id:ch3cooh393:20141211225251p:plain

名前は仮に「blog-notification」としました。

f:id:ch3cooh393:20141211225302p:plain

f:id:ch3cooh393:20141211225309p:plain

f:id:ch3cooh393:20141211225325p:plain

以上でMobile Serviceでのサービスの作成は完了です。

プッシュ通知を受け取るための処理

次にWindows Phoneアプリ側の処理を追加しましょう。App2という既存のアプリプロジェクトがあるとします。Visual Studioで開きます。

f:id:ch3cooh393:20141212022604p:plain

Visual Studioでプッシュ通知の追加

右ペインのソリューションエクスプローラーのApp2を右クリックします。コンテキストメニューが表示されるので、[追加(D)]、[プッシュ通知(P)...]の順に選択します。

f:id:ch3cooh393:20141212022628p:plain

あとはウィザードに従って必要な情報を設定していきます。

f:id:ch3cooh393:20141212022642p:plain

f:id:ch3cooh393:20141212022652p:plain

f:id:ch3cooh393:20141212022701p:plain

先ほど作成したサービスとアプリを関連付けます。

f:id:ch3cooh393:20141212022710p:plain

f:id:ch3cooh393:20141212022720p:plain

「プッシュ通知の追加」を実行すると、本来しなければいけない作業のほとんどを自動化することができます。

  • アプリケーションをWindowsストアとの関連付け
  • Windows Azure Mobile Service SDKを追加
  • Azure Mobile ServiceへWNSのクライアントトークンを登録

すごい横着した感がありますが、これでアプリでMobile Seviceのサービスを利用することができるようになりました。

App.xaml.csに通知チャンネルの登録処理を追加する

一通り設定作業が終わったので、「通知チャンネルの取得」と「通知チャンネルを通知ハブへ登録」の処理をApp.xaml.csのOnLaunchedメソッドに追加しましょう。

App.xaml.csを開き、下記のusingディレクティブが追加されていることを確認します。Microsoft.WindowsAzure.MobileServices名前空間を宣言しているのは拡張メソッドを利用するためです

// add
using Windows.Networking.PushNotifications;
using Microsoft.WindowsAzure.MobileServices;

Mobile Serviceとのやり取りをおこなうフィールド変数が追加されているのを確認します。

    /// <summary>
    /// 既定の Application クラスに対してアプリケーション独自の動作を実装します。
    /// </summary>
    public sealed partial class App : Application
    {
        // http://go.microsoft.com/fwlink/?LinkId=290986&clcid=0x411
        public static Microsoft.WindowsAzure.MobileServices.MobileServiceClient blog_notificationClient = new Microsoft.WindowsAzure.MobileServices.MobileServiceClient(
        "https://blog-notification.azure-mobile.net/",
        "<youre access key>");

通知チャンネルを取得し、取得したそれを通知ハブへ非同期で登録する処理を

        protected override async void OnLaunched(LaunchActivatedEventArgs e)
        {
#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            // Add: 通知チャンネルを取得する
            var chanel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();

            // Add: 取得した通知チャンネルを通知ハブへ登録する
            var push = blog_notificationClient.GetPush();
            await push.RegisterNativeAsync(chanel.Uri);

これでアプリ側の処理は完了です。Windows Phoneシミュレータでデバッグ実行して頂き、アプリを起動した状態にしておいてください(OnLaunchedメソッドを実行させて、通知チャンネルを通知ハブへ登録させるため)。

通知ハブのデバッグからプッシュを送る

Azureの管理ページにアクセスします。SERVICE BUSをクリックして、先ほど作成したblog-notificationを選択します。

f:id:ch3cooh393:20141212024022p:plain

通知ハブタブを選択して、blog-notification-hubを選択します。

f:id:ch3cooh393:20141212024029p:plain

デバッグタブを選択します。プラットフォームにはWindowsを選択して、通知の種類から「トースト」を選択すると、下図のようにテストメッセージのペイロードテンプレートが表示されると思います。

ページ下部中央の[送信ボタン]をクリックして、プッシュ通知を送ります。

f:id:ch3cooh393:20141212024204p:plain

送信すると1分かからずWindows Phoneシミュレータの方にプッシュ通知されます。

f:id:ch3cooh393:20141212023857p:plain

てれれれーん。

(おまけ)Azure Service Bus SDKを使ってコンソールアプリからプッシュを送信する

通知ハブにはSDKが提供されており、当然ですが自動で実行してくれるジョブを作成することができます。

ジョブから通知ハブに接続するために接続文字列が必要になります。接続文字列は、Azure管理ページの通知ハブを見ている時にタブバー(?)に表示されている[接続情報]のボタンをクリックします。

f:id:ch3cooh393:20141211234354p:plain

コンソールアプリプロジェクトにAzure Service Bus SDKをインストールして、以下のようなコードを書きます。XMLを組み立てる処理はもっと適切な方法がある気もしますが面倒なのでStringBuilderを使っています。

// 接続文字列
var connnectionString = "Endpoint=sb://example-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=<your key>";

// ハブ名
var hubName = "<your hub name>";

// テスト送信か?(WNSの場合はあまり関係なさそう)
// Production(本番)にプッシュ通知を送信する場合は false
// Development(開発)にプッシュ通知を送信する場合は true
var enableTestSend = false;

// 接続文字列からNotificationHubClientオブジェクトを生成する
var hubClient = NotificationHubClient.CreateClientFromConnectionString(connnectionString, hubName, enableTestSend);

// ここで「kazuakixの日記」が更新されているか調べる
var isUpdated = GetKazuakixNoNikki();
if (!isUpdated)
{
    // 更新されてなければプッシュは送らない
    return;
}

// ペイロード(メッセージ)を作成する
var message = "かずあきさんのブログが更新されたよ!見てね星";

var sb = new System.Text.StringBuilder();
sb.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?> ");
sb.AppendLine("<toast> ");
sb.AppendLine("<visual><binding template=\"ToastText01\">");
sb.AppendFormat("<text id=\"1\">{0}</text>", message);
sb.AppendLine();
sb.AppendLine("</binding>");
sb.AppendLine("</visual>");
sb.AppendLine("</toast>");
var payload = sb.ToString();

// 通知を送信!!!!
await hubClient.SendWindowsNativeNotificationAsync(payload);

上記の通知ハブのAPIを使用したサンプルコードを実行すると事前に登録していたWindowsデバイスに向けてプッシュでトースト通知されるはずです。

_人人人人人人人人人人人人人人人人人人人人人人人人_
> かずあきさんのブログが更新されたよ!見てね星 <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄ ̄

おわり。

*1:なお、本記事ではSilverlightの方のWindows Phoneアプリの話はしません

*2:通知する処理まで入れると3ステップ