位置情報を取得する

取得したロケーションサービス(位置情報を扱う仕組み)のデータを、以下の様な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);
            });
        }