Windows Phone 7.1 Locationの使い方

Location、Location…過去のブログのポストを見ていたら、まとまって説明しているものが無いので、改めて通して紹介します。D1-401のセミナーでも紹介したことだし。

地図やナビゲーション、自分の周辺に関わる何かを扱うアプリケーションでは、位置情報取得は必須です。Windows Phone 7.1にはSystem.Device.Locaiton名前空間に、GeoCoordinateWatcherクラスが用意されていて、デバイスの現在位置の取得が可能です。位置情報というとGPS?って思う人も沢山いらっしゃるでしょう。しかしこのクラス名にはGPSのジの字もありませんね。位置情報は、GPSで取得できるだけでなく、携帯基地局やWifiのルーター等、色々なソースから取得が可能です。純粋に位置情報を取得することを考えると、GPSは位置を取得するための単なる手段であることに気がつくでしょう。

Windows Phoneの位置情報取得機能は、GPSやその他の位置情報取得をひっくるめて位置情報を提供するように作られています。
と、能書きはこれぐらいにして、早速使い方を説明していきます。

先ずは、プロジェクトの参照設定に、System.Deviceコンポーネントを追加します。

プログラムの適切な場所に、

using System.Device;

を書いておきます。
https://blogs.msdn.com/b/hirosho/archive/2011/10/11/windowsphone71sensorprogramingbasis.aspx で説明したセンサーと処理の流れは似ています。同期的な位置情報取得と非同期的な位置情報取得方法をTPOに合わせて選択可能です。

先ずは、同期的な処理から。

var watcher = new GeoCoordinateWatcher(GeoPosiitonAccuracy.Default);
watcher.Start();
var position = watcher.Position;
watcher.Stop();

基本はこれだけ。ただし、watcherのStartメソッドをコールしてから、位置情報が取れるまでは初期化や情報収集などで時間がかかる場合があるので、実際にはStatusプロパティがReadyになるまで待つ必要はあります。
Positionは、Locationというプロパティが用意されていて、その中にLatitude(緯度)、Longitude(経度)が格納されています。他にもいくつかプロパティは用意されているのですが、まx、Altitudeという高度を示すプロパティだけあると、このポストでは行っておくことにします。

さて、非同期処理はといえば、センサーの時と同様、GeoCoordinateWatcherのインスタンスはクラスのメンバー変数として定義しておきます。

private GeoCoordinateWatcher watcher;

初期化フェーズの時に、インスタンスを作成し、位置情報が更新した時にコールされるハンドラーを登録します。

watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
watcher.PositionChanged += new EventHandler<GeoPositionChanged<GeoCoordinate>>(watcher_PositionChanged);

そして、いよいよ位置情報が必要になるタイミングで、

watcher.Start();

をコールして、位置取得処理を開始します。
すると、watcherは、”Initializing”→”Ready"に状態変更(watcher_StatusChangedがコールされ、引数でStatusが渡される)しつつ、”Ready”になって位置情報が取得できたら、watcher_PositionChangedがコールされます。
ハンドラーのコードは以下のようになります。

private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        var timestamp = e.Position.Timestamp;
        var location = e.Position.Location;
        var altitude = location.Altitude;    // 高度
        var latitude = location.Latitude;   // 緯度
        var longitude = location.Longitude; // 経度
        ... 各種処理
    });
}

他にも、HorizontalAccuracyやVerticalAccuracyなど、位置情報の誤差なども取得可能です。
そして、使い終わったら、

watcher.Stop();

で、計測を終了します。こちらも無駄に動かしていると電池を食うので、終わったらとっととStopしてくださいね。

以上、位置情報の取得はかなり簡単なのがお分かりかと思います。後は計測した値をどう使うかが腕の見せ所。例えばセンサーの値と組み合わせ、写真を撮った時の位置、デバイスが向いていた方向、姿勢情報も合わせて記録しておいて、後で臨場感あふれる3Dアルバムなんていかが?