気楽なソフト工房

プログラミングについていろいろな記事を書いています。



mykonos2008

Author:mykonos2008
システムエンジニアとして働いている30代の会社員です。
仕事や趣味でプログラムを書いている方の役に立つ記事を書いていきたいと思っています。
ご意見、ご感想はこちらまで
If you are an english speaker,Please visit my english blog.

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
今回、開発するアプリは、場所を指定された場所の近辺にある宿泊施設を検索し、その空き情報を表示するというアプリです。
宿泊施設の情報は、楽天のWebサービスから取得します。

まだ、開発を始めたばかりですが、ここまで開発した画面は以下のような感じです。



このアプリでは、検索する場所を携帯基地局やGPS等の位置情報サービスから取得する方法と
地図で指定する方法の2通りを想定しています。
本日は、Windows PhoneのSilverlight APIで、位置情報サービスを使って位置情報を取得する方法をご紹介します。

Windows Phoneの位置情報サービスは、GPSやWi-Fi、3Gアンテナなどから得られる位置情報にアクセスするためのAPIで、
「System.Device.Location」名前空間から提供されています。

「System.Device.Location」を利用するためには、まず、「System.Device」への参照を追加する必要があります。 そして、以下のように、using句を記述します。

[MailPage.xaml.cs]
   using System.Device.Location;

位置情報サービスにアクセスするためのProxyの役割を果たすのが「GeoCoordinateWatcher」というクラスです。
まず、この型をMainPageのインスタンス変数として宣言します。アプリケーションを通して、位置情報サービスを
使用する場合、アプリケーション中で単一のインスタンスになるように、Singletonパターンでラップするなど
考えた方が良さそうですが、一旦ページのインスタンスとして宣言しました。

[MailPage.xaml.cs]
   private GeoCoordinateWatcher watcher;

そして、ページのコンストラクタで、GeoCoordinateWatcherをインスタンス化します。

[MailPage.xaml.cs]
  public MainPage()
  {
      InitializeComponent();

      //位置情報サービスを初期化する
      watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);

      //PositionChangedイベントを受け取る感覚をメートル単位で指定
      watcher.MovementThreshold = 20;

      //イベントハンドラを登録する
      watcher.StatusChanged += new EventHandler(watcher_StatusChanged);
      watcher.PositionChanged += new EventHandler>(watcher_PositionChanged);

  }

コンストラクタに指定する「GeoPositionAccuracy」とは、位置情報サービスに求める正確性を設定する引数です。
「Default」と「High」から選択可能ですが、実際にどのデバイス(GPSなど)から情報を得るかを直接指定することは
できません。位置情報サービスが、現在アクセス可能なデバイスから要求に見合うものを選択します。
今回開発するアプリではそこまでの精度は必要ないので、「Default」設定にします。

GeoCoordinateWatcherは、デバイスの位置が移動すると、位置が変わったことをイベントで通知してくれますが、
その通知の発生感覚を調整するのが「MovementThreshold」です。

MovementThresholdには前回、位置情報の変更通知を受け取ってから、次回に受け取るまでの間の移動距離を
メートル単位で指定します。既定値は0で、少しでも位置が移動した場合、通知を受取ります。
場合によってはGPSのノイズで通知が発生するケースもあると、ドキュメントには記載されています。

また、値を小さく設定すると、その分、電力消費量は大きくなるので、20メートル以上を設定しておくことが
望ましいようです。

次にイベントハンドラを登録します。「StatusChanged」イベントは、位置情報サービスの状態が変化した時に 発生するイベントです。

[MailPage.xaml.cs]
  private void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
  {
      switch (e.Status)
      {
          //位置情報サービスが使用できない状態
          case GeoPositionStatus.Disabled:
              if (watcher.Permission == GeoPositionPermission.Denied)
              {
                  message.Text = "位置情報サービスが無効になっています。";
              }
              else
              {
                  message.Text = "位置情報サービスを使用できません。";
              }
              if (watcher.Position.Location.IsUnknown)
                  searchBtn.IsEnabled = false;
              break;
          //位置情報サービスが初期化中の状態
          case GeoPositionStatus.Initializing:
              message.Text = "位置情報サービスを準備しています。";
              break;
          //位置情報サービスが位置情報を取得できない状態
          case GeoPositionStatus.NoData:
              message.Text = "データが取得できません。";
              if (watcher.Position.Location.IsUnknown)
                  searchBtn.IsEnabled = false;
              break;
          //位置情報を取得できる状態
          case GeoPositionStatus.Ready:
              message.Text = "";
              searchBtn.IsEnabled = true;
              break;
      }
  }

位置情報サービスの状態は、ユーザの設定や端末の状態によって、変化します。
アプリケーション側では、その状態の変化を適切に処理する必要があります。
今回、開発しているアプリでは、位置情報サービスが使用可能な状態の場合のみ、
検索ボタンをタップできるように制御しています。最後に取得した位置情報がGeoCoordinateWatcherの
Positionプロパティに保存されるので、現在、位置情報サービスが取得できない状態でも
Positionプロパティに値が入っている場合は、ボタンをタップできるようにしています。

PositionChangedイベントは、位置情報の変更を受け取った際に、発生するイベントです。
今回のアプリでは、位置情報が変わる毎に処理する内容は無いので、特に処理はしていません。
(説明のためにイベントハンドラを登録しています。)

ここまで準備が完了したので、GeoCoordinateWatcherのStart()メソッドをコールし、位置情報の取得を開始します。
今のところ、この処理はMainPageの「OnNavigatedTo」で行なっています。

[MailPage.xaml.cs]
  protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  {
      watcher.Start();
  }

検索ボタンがクリックされてから、位置情報の取得を開始する方法も考えられますが、
状況によっては初期化に時間がとられる可能性があるため、ページに遷移した時に
スタートするようにしました。

ここでは、詳しく述べませんが、位置情報サービスを使用するアプリをマーケットに
登録する場合、満たさなければならない要件がいくつかあります。その中の
ひとつに、ユーザに対して、位置情報サービスを使用することを通知し、
承諾を得るというものがあります。OnNavigatedToで、GeoCoordinateWatcherのStart()メソッドをコールしているので、
これをクリアするためには、このページに遷移する前に、承諾を得るためのページを挟み込む必要がありそうです。

最後にユーザが当ページから他のページに遷移する際に、位置情報サービスを停止する処理を記述しています。

[MailPage.xaml.cs]
  protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
  {
      watcher.Stop();
      searchBtn.IsEnabled = false;
  }

コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://csfun.blog49.fc2.com/tb.php/106-c63e0af2

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。