チュートリアル:Notification Hubs と Bing Spatial Data を使用して場所に基づいたプッシュ通知を送信する
このチュートリアルでは、Azure Notification Hubs と Bing Spatial Data を使用して場所に基づいたプッシュ通知を送信する方法について学習します。
このチュートリアルでは、次の手順を実行します。
- データ ソースを設定する
- UWP アプリケーションを設定する
- バックエンドを設定する
- ユニバーサル Windows プラットフォーム (UWP) アプリでプッシュ通知をテストする
前提条件
- Azure サブスクリプション。 Azure サブスクリプションをお持ちでない場合は、開始する前に無料の Azure アカウントを作成してください。
- Visual Studio 2015 Update 1 以降 (Community Edition)。
- 最新バージョンの Azure SDK。
- Bing マップ デベロッパー センター アカウント。アカウントの作成は無料です。作成したアカウントは Microsoft アカウントに関連付けることができます。
データ ソースを設定する
Bing Maps デベロッパー センターにログインします。
一番上のナビゲーション バーで、 [データ ソース] を選択してから、 [Manage Data Sources] (データ ソースの管理) を選択します。
既存のデータ ソースがない場合は、データ ソースを作成するためのリンクが表示されます。 [Upload data as a data source] (データをデータ ソースとしてアップロードする) を選択します。 [データ ソース]>[データのアップロード] メニューを使用することもできます。
次の内容を含むファイル
NotificationHubsGeofence.pipe
をハード ドライブ上に作成します。このチュートリアルでは、サンフランシスコのウォーターフロントの領域を形作るサンプルのパイプ ベース ファイルを使用します。Bing Spatial Data Services, 1.0, TestBoundaries EntityID(Edm.String,primaryKey)|Name(Edm.String)|Longitude(Edm.Double)|Latitude(Edm.Double)|Boundary(Edm.Geography) 1|SanFranciscoPier|||POLYGON ((-122.389825 37.776598,-122.389438 37.773087,-122.381885 37.771849,-122.382186 37.777022,-122.389825 37.776598))
このパイプ ファイルは、次のエンティティを表しています。
[Upload a data source] (データ ソースをアップロードする) ページで、次のアクションを実行します。
[データ形式] として [パイプ] を選択します。
前の手順で作成した
NotificationHubGeofence.pipe
ファイルを参照して選択します。[アップロード] ボタンを選択します。
Note
[マスター キー] に、 [クエリ キー] とは異なる新しいキーを指定するよう求められる場合があります。 ダッシュボードで新しいキーを作成して、データ ソースのアップロード ページを更新してください。
データ ファイルをアップロードしたら、そのデータ ソースを確実に発行する必要があります。 前と同様に [データ ソース] ->[データ ソースの管理] を選択します。
一覧のデータ ソースを選択してから、 [アクション] 列で [発行] を選択します。
[Published Data Sources] (発行されたデータ ソース) タブに切り替え、一覧にデータ ソースが表示されることを確認します。
[編集] を選択します。 データ内のどの場所に導入したかが (一目で) わかります。
この時点では、作成したジオフェンスの境界がポータルに表示されません。指定した場所が適切に収まっていることを確認するだけでかまいません。
これで、データ ソースの要件がすべて揃いました。 API 呼び出しに使用する要求 URL について詳しい情報を確認するには、Bing Maps デベロッパー センターで [Data sources](データ ソース) を選択し、 [Data Source Information](データ ソース情報) を選択します。
クエリ URL は、デバイスが現在、場所の境界内に存在するかどうかをチェックするためのクエリを実行できるエンドポイントです。 このチェックを実行するには、クエリ URL に対して、次のパラメーターが追加された GET 呼び出しを実行するだけで済みます。
?spatialFilter=intersects(%27POINT%20LONGITUDE%20LATITUDE)%27)&$format=json&key=QUERY_KEY
Bing Maps は、デバイスがジオフェンス内に存在するかどうかを確認するための計算を自動的に実行します。 ブラウザー (または cURL) から要求を実行すると、標準の JSON 応答が取得されます。
この応答が返されるのは、実際にその地点が、指定された境界の範囲内にあるときだけです。 存在しない場合は、空の結果のバケットが取得されます。
UWP アプリケーションを設定する
Visual Studio で、 [空白のアプリ (ユニバーサル Windows)] タイプの新しいプロジェクトを起動します。
プロジェクトを作成したら、アプリ自体のテスト ハーネスが必要です。 ジオフェンス インフラストラクチャを構成するさまざまな要素を設定していきましょう。 このソリューションでは Bing サービスを使用しようとしているため、特定の場所フレームに関するクエリを実行できるパブリック REST API エンドポイントが存在します。
http://spatial.virtualearth.net/REST/v1/data/
これを機能させるには、次のパラメーターを指定します。
データ ソース ID とデータ ソース名 – Bing マップ API では、さまざまな分類のメタデータ (位置情報、企業の営業時間など) がデータ ソースに格納されます。
エンティティ名 – 通知の基準点として使用するエンティティです。
Bing Maps API キー – 前に Bing デベロッパー センター アカウントを作成するときに取得したキー。
これでデータ ソースが準備できたので、UWP アプリケーションの操作を開始できます。
アプリケーションの場所サービスを有効にします。 ソリューション エクスプローラーで
Package.appxmanifest
ファイルを開きます。開いたばかりのパッケージ プロパティ タブで、 [機能] タブに切り替えてから、 [場所] を選択します。
ソリューション内に
Core
という名前の新しいフォルダーを作成し、その中にLocationHelper.cs
という名前の新しいファイルを追加します。LocationHelper
クラスには、システム API 経由でユーザーの場所を取得するためのコードが含まれています。using System; using System.Threading.Tasks; using Windows.Devices.Geolocation; namespace NotificationHubs.Geofence.Core { public class LocationHelper { private static readonly uint AppDesiredAccuracyInMeters = 10; public async static Task<Geoposition> GetCurrentLocation() { var accessStatus = await Geolocator.RequestAccessAsync(); switch (accessStatus) { case GeolocationAccessStatus.Allowed: { Geolocator geolocator = new Geolocator { DesiredAccuracyInMeters = AppDesiredAccuracyInMeters }; return await geolocator.GetGeopositionAsync(); } default: { return null; } } } } }
UWP アプリでユーザーの場所を取得する方法の詳細については、「ユーザーの位置情報の取得」を参照してください。
位置情報の取得機能が正しく動作することを確認するために、メイン ページ (
MainPage.xaml.cs
) のコードを開いてください。MainPage
コンストラクター内にLoaded
イベントの新しいイベント ハンドラーを作成します。public MainPage() { this.InitializeComponent(); this.Loaded += MainPage_Loaded; }
イベント ハンドラーには、次のコードを実装します。
private async void MainPage_Loaded(object sender, RoutedEventArgs e) { var location = await LocationHelper.GetCurrentLocation(); if (location != null) { Debug.WriteLine(string.Concat(location.Coordinate.Longitude, " ", location.Coordinate.Latitude)); } }
アプリケーションを実行し、そこからユーザーの場所へのアクセスを許可します。
アプリケーションの起動後、 出力 ウィンドウに座標が表示されます。
これで場所の取得が機能することがわかったので、もう使用しなければ、Loaded イベント ハンドラーは必要に応じて削除できます。
次に、位置情報の変化をキャプチャします。
LocationHelper
クラスで、PositionChanged
のイベント ハンドラーを追加します。geolocator.PositionChanged += Geolocator_PositionChanged;
この実装では、場所の座標を [出力] ウィンドウに表示します。
private static async void Geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args) { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { Debug.WriteLine(string.Concat(args.Position.Coordinate.Longitude, " ", args.Position.Coordinate.Latitude)); }); }
バックエンドを設定する
GitHub から .NET バックエンド サンプルをダウンロードします。
ダウンロードが完了したら、
NotifyUsers
フォルダーを開いてから、Visual Studio でNotifyUsers.sln
ファイルを開きます。AppBackend
プロジェクトを スタートアップ プロジェクト として設定し、起動します。このプロジェクトはターゲット デバイスにプッシュ通知を送信するように既に構成されているため、実行する必要があるのは、通知ハブ用の正しい接続文字列を指定することと、ユーザーがジオフェンス内に存在する場合にのみ通知を送信するための境界の識別を追加することの 2 つだけです。
接続文字列を構成するには、
Models
フォルダーのNotifications.cs
を開きます。NotificationHubClient.CreateClientFromConnectionString
関数には、Azure Portal ( [設定] の [アクセス ポリシー] ページ内を参照) で取得できる通知ハブに関する情報が含まれています。 更新した構成ファイルを保存します。Bing Maps API の結果のモデルを作成します。 それを行うための最も簡単な方法として、
Models
フォルダーを開き、 [追加]>[クラス] を選択します。 これにGeofenceBoundary.cs
という名前を付けます。 完了したら、最初のセクションで取得した API 応答から JSON をコピーします。 Visual Studio で、 [編集]>[形式を選択して貼り付け]>[JSON をクラスとして貼り付ける] を使用します。この方法により、オブジェクトが意図したとおりに確実に逆シリアル化されます。 結果として得られるクラス セットは、次のクラスのようになります。
namespace AppBackend.Models { public class Rootobject { public D d { get; set; } } public class D { public string __copyright { get; set; } public Result[] results { get; set; } } public class Result { public __Metadata __metadata { get; set; } public string EntityID { get; set; } public string Name { get; set; } public float Longitude { get; set; } public float Latitude { get; set; } public string Boundary { get; set; } public string Confidence { get; set; } public string Locality { get; set; } public string AddressLine { get; set; } public string AdminDistrict { get; set; } public string CountryRegion { get; set; } public string PostalCode { get; set; } } public class __Metadata { public string uri { get; set; } } }
次に、
Controllers
>NotificationsController.cs
を開きます。 ターゲットの経度と緯度を考慮するように Post 呼び出しを更新します。 それを行うには、関数シグネチャにlatitude
とlongitude
の 2 つの文字列を追加します。public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag, string latitude, string longitude)
プロジェクト内に
ApiHelper.cs
という名前の新しいクラスを作成します。これは、Bing に接続して、地点の境界の交差をチェックするために使用します。 次のコードに示すように、IsPointWithinBounds
関数を実装します。public class ApiHelper { public static readonly string ApiEndpoint = "{YOUR_QUERY_ENDPOINT}?spatialFilter=intersects(%27POINT%20({0}%20{1})%27)&$format=json&key={2}"; public static readonly string ApiKey = "{YOUR_API_KEY}"; public static bool IsPointWithinBounds(string longitude,string latitude) { var json = new WebClient().DownloadString(string.Format(ApiEndpoint, longitude, latitude, ApiKey)); var result = JsonConvert.DeserializeObject<Rootobject>(json); if (result.d.results != null && result.d.results.Count() > 0) { return true; } else { return false; } } }
重要
API エンドポイントは必ず、先ほど Bing デベロッパー センターから取得したクエリ URL に置き換えてください (API キーも同様)。
クエリに対する結果が存在する場合は、指定された地点がジオフェンスの境界内にあることを示すため、この関数は
true
を返します。 結果が存在しない場合、Bing はその地点が参照フレームの外部にあることを通知しているため、この関数はfalse
を返します。NotificationsController.cs
で、switch ステートメントの直前にチェックを作成します。if (ApiHelper.IsPointWithinBounds(longitude, latitude)) { switch (pns.ToLower()) { case "wns": //// Windows 8.1 / Windows Phone 8.1 var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + "From " + user + ": " + message + "</text></binding></visual></toast>"; outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag); // Windows 10 specific Action Center support toast = @"<toast><visual><binding template=""ToastGeneric""><text id=""1"">" + "From " + user + ": " + message + "</text></binding></visual></toast>"; outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag); break; } }
UWP アプリでプッシュ通知をテストする
UWP アプリで、通知をテストできるようになりました。
LocationHelper
クラスに、SendLocationToBackend
という新しい関数を作成します。public static async Task SendLocationToBackend(string pns, string userTag, string message, string latitude, string longitude) { var POST_URL = "http://localhost:8741/api/notifications?pns=" + pns + "&to_tag=" + userTag + "&latitude=" + latitude + "&longitude=" + longitude; using (var httpClient = new HttpClient()) { try { await httpClient.PostAsync(POST_URL, new StringContent("\"" + message + "\"", System.Text.Encoding.UTF8, "application/json")); } catch (Exception ex) { Debug.WriteLine(ex.Message); } } }
注意
POST_URL
をデプロイされた Web アプリケーションの場所に設定します。 当面はローカルに実行してもかまいませんが、パブリック バージョンをデプロイするときは、外部プロバイダーでホストする必要があります。UWP アプリをプッシュ通知用に登録します。 Visual Studio で、 [プロジェクト]>[ストア]>[アプリケーションをストアと関連付ける] の順に選択します。
開発者アカウントにサインインしたら、既存のアプリを選択するか、または新しくアプリを作成してそこにパッケージを関連付けてください。
デベロッパー センターに移動し、作成したアプリを開きます。 [サービス]>[プッシュ通知]>[Live Services site]\(Live サービス サイト\) の順に選択します。
このサイトで、アプリケーションのシークレットとパッケージ SID をメモします。 Azure Portal では、この両方が必要です。通知ハブを開いて、 [設定]>[Notification Services]>[Windows (WNS)] を選択し、必要なフィールドに情報を入力します。
[保存] を選択します。
ソリューション エクスプローラーで [参照設定] を開いて、 [NuGet パッケージの管理] を選択します。 Microsoft Azure Service Bus マネージド ライブラリへの参照を追加します。単純に
WindowsAzure.Messaging.Managed
を検索し、それをプロジェクトに追加します。テストのために、再度
MainPage_Loaded
イベント ハンドラーを作成し、そこに次のコード スニペットを追加します。var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync(); var hub = new NotificationHub("HUB_NAME", "HUB_LISTEN_CONNECTION_STRING"); var result = await hub.RegisterNativeAsync(channel.Uri); // Displays the registration ID so you know it was successful if (result.RegistrationId != null) { Debug.WriteLine("Reg successful."); }
このコードは、アプリを通知ハブに登録します。 これで準備が整いました。
LocationHelper
のGeolocator_PositionChanged
ハンドラー内に、場所をジオフェンスの内部に強制的に配置するテスト コードを追加できます。await LocationHelper.SendLocationToBackend("wns", "TEST_USER", "TEST", "37.7746", "-122.3858");
実際の座標 (現時点では境界内にない可能性があります) を渡しているわけではなく、事前に定義されたテスト値を使用しているため、更新時に次の通知が表示されます。
次のステップ
このソリューションを運用環境に対応させるには、いくつかの手順を実行する必要があります。
- 最初に、ジオフェンスが動的であることを確認する必要があります。 それには、Bing API を使用した何らかの追加の作業で、既存のデータ ソース内の新しい境界をアップロードできることが必要です。 詳細については、Bing Spatial Data Services API ドキュメントを参照してください。
- 次に、適切な参加者に対して確実に通知を配信するために、 タグ付けによってターゲットを指定する場合があります。
このチュートリアルに示されているソリューションでは、多様なターゲット プラットフォームが存在する可能性のあるシナリオが説明されているため、ジオフェンシングがシステム固有の機能に制限されません。 しかし、ユニバーサル Windows プラットフォームには、 細かい設定なしにジオフェンスを検出する機能が備わっています。