概要
Windows Phone Location Serviceへアクセスする手段を提供してます。
Windows Phone 7.5("Mango"アップデート)からはWindows Phone エミュレータの標準機能としてGPSシミュレータが付きますが、それ以前の開発環境では「GPSをエミュレートする」を参考にして頂きながら、PC上での試験をおこなうようにするとテストがスムーズかもしれません。
名前空間:System.Device.Location
- System.Object
- System.Device.Location.GeoCoordinateWatcher
Tips
位置情報を取得する
取得したロケーションサービス(位置情報を扱う仕組み)のデータを、以下の様なUIで表示させてみましょう。一番上からロケーションサービスのステータス、緯度(latitude)、経度(longitude)の値を表示させています。
System.Device.Location名前空間のクラスを使用して位置情報を取得します。参照の追加ダイアログにて「System.Device」を参照しておきます。更にusingディレクティブに追加しておきましょう。
using System.Device.Location; // for Location Service using System.Windows; using Microsoft.Phone.Controls; using System.Windows.Navigation;
GPSデバイスから取得した位置情報をアプリケーションで受け取るにGeoCoordinateWatcherクラスを使用します。
下記のサンプルコードではページ遷移後にOnNavigatedToメソッドが実行され、GeoCoordinateWatcherインスタンスの生成をおこない、位置情報の取得を開始します。
物理的なセンサーデバイスからの入力を受け取るため、位置情報を取得するのは殆どのケースでは1秒未満に位置情報が取得できますが、取得が遅い場合1分掛かることも有り得ます。
高精度で位置情報を取得したい場合はコンストラクタ引数にGeoPositionAccuracy.Highを指定しています。精度は低くても測定速度を上げたい場合はGeoPositionAccuracy.Defaultを指定します。
namespace GeoCoordinateWatcherTest { public partial class MainPage : PhoneApplicationPage { // コンストラクター public MainPage() { InitializeComponent(); } GeoCoordinateWatcher watcher; // ページ遷移されてきた時に呼び出される protected override void OnNavigatedTo(NavigationEventArgs e) { // GeoCoordinateWatcherのインスタンスを生成する // Highを指定すると高精度で位置測定する watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // 精度よりも測定速度を優先する場合はDefaultを指定する //watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default); // 位置が変更されたことを判定する最短距離(単位:メートル) watcher.MovementThreshold = 20; // 位置が変更された時に発生するイベントハンドラを追加 watcher.PositionChanged += watcher_PositionChanged; // ロケーションサービスの状態変化時に発生するイベントハンドラを追加 watcher.StatusChanged += watcher_StatusChanged; // データの取得を開始する watcher.Start(); }
以上で位置情報の取得を開始します。ロケーションサービスのステータス変更イベント、位置が変更したイベントの取得の仕方について後述します。
ロケーションサービスの状態が変化された時のイベント
ロケーションサービスの状態が変化するとStatusChangedイベントが発生します。ここではイベントハンドラで状態を受け取り、TextBlockコントロールに日本語で説明を表示させています。
TextBlockの値を変更するにはUIスレッドからおこなう必要があります。ただ、GeoCoordinateWatcherからのイベントは別のスレッドから返ってくる為、BeginInvokeメソッドを使ってUIスレッド上で非同期に実行しています。
// 状態が変更された場合に呼ばれるイベントハンドラ void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e) { // TextBlockの値を変更したいのでUIスレッド上で実行させる Deployment.Current.Dispatcher.BeginInvoke(() => { // ステータスの内容によって表示する文言を変更する switch (e.Status) { case GeoPositionStatus.Initializing: labelStatus.Text = "初期化中"; break; case GeoPositionStatus.Ready: labelStatus.Text = "動作中"; break; case GeoPositionStatus.NoData: labelStatus.Text = "動作中だが、位置情報が取得できていない"; break; case GeoPositionStatus.Disabled: labelStatus.Text = "非サポートか無効にされています"; break; } }); }
移動して位置情報が変更された時のイベント
前回測位した位置より移動し、MovementThresholdプロパティに設定した最短距離以上移動した場合にPositionChangedイベントが発生します。ここではイベントハンドラで位置情報を受け取り、TextBlockコントロールに整形された値を表示しています。
こちらのイベントも別スレッドで通知される為、BeginInvokeメソッドを使用しています。
// 位置情報が変更された場合に呼ばれるイベントハンドラ void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) { // TextBlockの値を変更したいのでUIスレッド上で実行させる Deployment.Current.Dispatcher.BeginInvoke(() => { double latitude = e.Position.Location.Latitude; double longitude = e.Position.Location.Longitude; labelLatitude.Text = string.Format("{0:0.0000}", latitude); labelLongitude.Text = string.Format("{0:0.0000}", longitude); }); }