Windows Phoneアプリケーション開発入門

第21回Bing Mapsで遊んでみよう!(2)

はじめに

Windows Phone 7のローンチイベントで年末商戦に向けて、アメリカのDell、台湾のHTC、韓国のSamsungとLGの4メーカーから以下の10種類の端末が発表されました。

  • HTC 7 Surround
  • HTC HD 7
  • HTC 7 Trophy
  • HTC 7 Mozart
  • HTC 7 Pro
  • Dell Venue Pro
  • Samsung Focus
  • Samsung Omnia 7
  • LG Optimus
  • LG Quantum

Windows Phone 7の第一弾の端末が既に10月21日にヨーロッパとアジアで発売されました。Microsoftの越川本部長がシンガポールで、どこのお店も売り切れ続出と現地の方々の白熱振りをTwitterで実況されていましたね。

いずれも日本のキャリアから発売される旨の発表はありませんが、日本に向けてのローカライズは進んでいるようです。日本語SDKが出てくるのが待ち遠しいですね。

さて、引き続きBing Mapsを使って遊んでみましょう。今回はGPS(Location Service)を使った現在地の表示をしてみましょう。

実装のための準備をしよう

前回ApplicationBarIconButtonを有効にしました。今回使用する機能を実行するためのアイコンボタンを定義します。

GPSを使って現在地にピンをプロットする「現在地」ボタン、航空写真モードと地図モードを切り替える「写真」ボタン、コード上から意図した箇所にピンを立てる「プロット」ボタンを用意します。

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton 
          IconUri="/Images/icon.png" 
          Click="btnLocation_Click" Text="現在地" />
        <shell:ApplicationBarIconButton 
          IconUri="/Images/icon.png" 
          Click="btnChangeMode_Click" Text="写真" />
        <shell:ApplicationBarIconButton 
          IconUri="/Images/icon.png" 
          Click="btnSetPin_Click" Text="プロット" />
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

航空写真モードと地図モードを切り替える「写真」ボタンは、前回実装した表示モードの切り替えになるので、説明は省かせて頂きます。

ズームレベルを変更する

Bing Mapsには、縮尺を定義する「ズームレベル」があります。0から20までの定義値をもっています。0の場合は世界地図レベル、20の場合は最接近したレベルです。

ただし日本の航空写真は、接近させるとデータがないのか画像が引き延ばされただけのものになってしまいます。綺麗に航空写真を表示させたい場合は、場所によりますが経験上レベルを18あたりにするのが良いかもしれません。

コード上からBing Mapsズームレベルを変更する方法をご紹介します。座標は、またまた僕の職場の近くの大阪駅(34.701189, 135.496016)を指しています。ZoomLevelは数字が大きいほど地図が詳細になり、逆に数字が小さいほどより多くの範囲を表示できます。

判りやすいように、最初から航空写真を表示させるモードにしています。ズームレベルの違いによる差を見てください。

ZoomLevel 10
private void btnLocation_Click(object sender, EventArgs e)
{
    map1.ZoomLevel = 10;
}
図1 ズームレベルを10にした場合の航空写真
図1 ズームレベルを10にした場合の航空写真
ZoomLevel 18
private void btnLocation_Click(object sender, EventArgs e)
{
    map1.ZoomLevel = 18;
}
図2 ズームレベルを18にした場合の航空写真
図2 ズームレベルを18にした場合の航空写真

ピンをプロットする

地図を使っているアプリケーションの場合、例えば目的地を示すためにピンを立てたい場合があります。そのような時は、Pushpinクラスのインスタンスを生成し、ピンを立てる位置を設定し、マップの子要素に追加します。

private void btnSetPin_Click(object sender, EventArgs e)
{
    var pin = new Pushpin();
    pin.Location = new GeoCoordinate(34.701189, 135.496016);
    map1.Children.Add(pin);
}
図3 ピンをプロットする
図3 ピンをプロットする

GPSの使い方

Windows Phone 7にはGPSデバイスが標準で搭載されています。Windows Mobile 6.5ではマネージコードからGPSデバイスにアクセスするにはP/InvokeでGPS APIを使用する必要がありましたから、Windows Phone 7で簡単にGPSを使えるようになって楽になったと思われるかもしれません。

GPSを使用するにはSystem.Deviceを参照しておく必要があります。

標準の設定だとSolution Explorerに [References] というディレクトリがあります。右クリックするとコンテキストメニューが出てきますので、[Add Reference...] を選択します。.NETタブからSystem.Deviceを参照します。

以降のソースコードは、System.Device.Location名前空間をusing宣言していることを前提としております。MainPage.xaml.csのコードの上のほうで以下の宣言を行っています。

// for location service
using System.Device.Location;

ここではGPSデバイスから取得した位置情報を受け取り、地図にピンをプロットする方法をご紹介します。

位置情報を取得する

緯度経度、位置情報に関する情報を取得するのにGeoCoordinateWatcherクラスを使います。現在地ボタンが押下されると、GeoCoordinateWatcherの初期化を行い、データの取得を開始します。

GeoCoordinateWatcher watcher;

private void btnLocation_Click(object sender, EventArgs e)
{
    // GeoCoordinateWatcherの初期化を行う
    watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
    watcher.MovementThreshold = 20;

    // 位置が変更された(PositionChanged)イベントをイベントハンドラに追加する
    watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
    
    // データの取得を開始する
    watcher.Start();
}

位置情報が変更されたイベントを受け取ると、watcher_PositionChangedが呼び出されます。このメソッドはメインUIスレッドとは異なるバックグラウンド スレッドから呼び出しされるため、UIスレッドに関連付けられたDispatcherに操作をデリゲートする必要があります。

ピンをプロットする処理をまとめたMyPositionChangedメソッドを、非同期処理としてイベント キューに追加し実行します。

// メインスレッド上で処理を行うため、位置情報をカスタムメソッドに渡します。
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    Deployment.Current.Dispatcher.BeginInvoke(() => MyPositionChanged(e));
}

GPSから受け取った情報をプロットする

GPSデバイスからの位置情報の変更を受け取り、マップ上に紫色のピンを立てていきます。

// PositionChangedイベントハンドラから呼ばれるカスタムメソッド
void MyPositionChanged(GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    double latitude = e.Position.Location.Latitude;
    double longitude = e.Position.Location.Longitude;

    // データを取得した位置を中心にする
    map1.Center = new GeoCoordinate(latitude, longitude);
    map1.ZoomLevel = 18;
    map1.Mode = new AerialMode();

    // 現在地に紫色のピンを立てる
    var pin = new Pushpin()
    {
        Background = new SolidColorBrush(Colors.Purple)
    };
    pin.Location = new GeoCoordinate(34.701189, 135.496016);
    map1.Children.Add(pin);
}
図4 現在地のデータを受信すると紫色のピンをプロットしていきます(写真はエミュレータで作った画像)
図4 現在地のデータを受信すると紫色のピンをプロットしていきます(写真はエミュレータで作った画像)

さいごに

簡単にGPSが使えることがお分かり頂けたかと思います。facebookやTwitter、いまココ!など位置情報を連携させるサービスが増えてきました。もしGPSが簡単に使えれば何々をやってみたい!という方は沢山いらっしゃるのではないでしょうか。現実世界との連携ほど楽しいものはありませんね。

GPSデバイスから位置情報を取得するには、Windows Phone 7の実機がないとできませんが、tmytさんがエミュレータのホストマシンとHTTPで通信を行い、ホストマシンに接続されているGPS座標をエミュレータから使用するコードを書いてくれています。

これを使えば、Windows Phone 7のエミュレータを使いながらGPSを使うことができます。次回は、GPSロガーのようなものを作ってみましょう。

以上で今回は終わりです。ありがとうございました。

おすすめ記事

記事・ニュース一覧