ContextMenuコントロールを使う、加速度センサー、GPSでの位置情報取得

2011年8月19日(金)
PROJECT KySS

加速度センサー

加速度センサーは、「端末の向き」や「重力の方向」を探知するセンサーで、現在端末が重力に対してどのような傾きになっているかを、数値として取得することができます。

このプログラムで実装する機能の動作を、下記に解説しておきます。

表示されたエミュレーターの右隅上にマウスカーソルを持っていくと、コントロールパネルが表示されます。[>>]アイコンをクリックすると、図5のように加速度センサーのエミュレーターが表示されます。表示されている●を操作することで、エミュレーターの端末の傾きが変化します。その値はX、Y、Zに表示されます。加速度センサーのエミュレーターの傾きに合わせて、表示されている「うどん」の画像の傾きも変化します。

3

図5:加速度センサーのエミュレーターの動きに合わせて「うどん」の画像の傾きも変化する(クリックで拡大)

サンプル一式は、会員限定特典としてダウンロードできます。記事末尾をご確認ください。
※サンプル実行でエラーが発生した場合は、「ソリューションのビルド」を実行後、再度、デバッグ開始を行ってください。

プロジェクトの作成

VS 2010のメニューから[ファイル(F)/新規作成(N)/プロジェクト(P)]を選択します。次に、「Windows Phone Application」を選択して、「名前(N)」に任意のプロジェクト名を指定します。ここでは「WP7_Accelerometer」という名前を付けています。Windows Phoneのバージョンには7.0を選択します。

ソリューションエクスプローラー内にImageというフォルダを作成し、1枚の画像を追加しておきます。

また、センサーを使用するため、VS2010メニューの「プロジェクト(P)/参照の追加(R)」と選択してMicrosoft.Device.Sensorsを追加しておいてください。

ダウンロードされたサンプルプログラムには画像ファイルは追加済です。

MainPage.xamlの編集とコントロールの追加

x:NameがPageTitleというTextBlockのTextプロパティにAccelerometerと指定します。ツールボックスからImageコントロールを1個配置し、WidthとHeighに150を指定し、SourceプロパティにImageフォルダ内の「うどん」の画像を指定します(図6)。MainPage.xaml内の要素が配置されている箇所を、リスト7のように編集します。

リスト7(MainPage.xaml)

(1)<Image.Projection>プロパティ要素内に<PlaneProjection>要素を配置し、x:NameにmyPlaneProjectionと指定しておきます。<Image.Projection>プロパティ要素では、UIElementのレンダリング時に射影を設定できます。<PlaneProjection>はオブジェクトに対する遠近法変換を表す要素です。
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  <Image Height="150" HorizontalAlignment="Left" Margin="140,203,0,0" Name="Image1" Stretch="Fill" VerticalAlignment="Top" Width="150" Source="/WP7_Accelerometer;component/Image/dekamori_mini.png">
    <Image.Projection> ■(1)
      <PlaneProjection x:Name="myPlainProjection"/> ■(1)
    </Image.Projection>
  </Image>
</Grid>

次に、ソリューションエクスプローラー内のMainPage.xamlを展開し、表示されるMainPage.xaml.vbをダブルクリックしてリスト8のロジックコードを記述します。

ロジックコードを記述する

リスト8(MainPage.xaml.vb)

Option Strict On
加速度計にアクセスする API を提供するMicrosoft.Devices.Sensors名前空間をインポートします。
Imports Microsoft.Devices.Sensors
Partial Public Class MainPage
  Inherits PhoneApplicationPage
~コード略~
Accelerometerクラスの新しいインスタンスであるmyAccelerometerメンバ変数を宣言します。Accelerometerクラスは、デバイスの加速度センサーにアクセスするWindows Phoneアプリケーションを提供するクラスです。
  Dim myAccelerometer As New Accelerometer

ページが読み込まれた時の処理

 AddHandlerメソッドで加速度センサーの値が変化した時に発生する、ReadingChangedイベントに、MyReadingChangedイベントハンドラを追加します。MyReadingChangedイベントは、別スレッドから呼び出されるためBeginInvokeメソッドで、非同期で処理を呼び出します。
Startメソッドで、計測を開始します。
  Private Sub MainPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    AddHandler myAccelerometer.ReadingChanged, Sub(senderValue As Object, eValue As AccelerometerReadingEventArgs)
      Deployment.Current.Dispatcher.BeginInvoke(Sub() MyReadingChanged(eValue))
    End Sub
  myAccelerometer.Start()
End Sub

非同期で呼び出される処理

ImageコントロールのProjectionプロパティに指定した、PlaneProjectionの、RotationX、RotationY、RotationZの値として、取得した計測結果に1000を乗算して指定します。
  Private Sub MyReadingChanged(resultE As AccelerometerReadingEventArgs)
    myPlainProjection.RotationX = resultE.X * 1000
    myPlainProjection.RotationY = resultE.Y * 1000
    myPlainProjection.RotationZ = resultE.Z * 1000
  End Sub

アプリケーション終了時の処理

Stopメソッドで計測を止めます。
  Private Sub MainPage_Unloaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
    myAccelerometer.Stop()
    myAccelerometer = Nothing
  End Sub
End Class

GPSでの位置情報取得

GPSのロケーションサービスを使って、デバイスの位置情報を取得します。

このプログラムで実装する機能の動作を、下記に解説しておきます。

表示されたエミュレーター内にはMapが表示されています。エミュレーターの右隅上にマウスカーソルを持っていくと、コントロールパネルが表示されます。[>>]アイコンをクリックし、表示された画面から「Location」タブをクリックします。「Search」の中に「京都」と入力し、虫眼鏡アイコンをクリックします。京都のマップが表示されます。タッチスクリーンの場合は2本の指で拡大縮小が可能です。タッチスクリーンでない場合は[+]と[-]の虫眼鏡アイコンで拡大縮小が可能です。

GPSエミュレーター内にある地図の、任意の場所をクリックしていくとピンが表示され、エミュレーター内のMapにも緯度、経度を記述したピンが表示されます。GPSエミュレーター内にも緯度、経度が表示されています(図6)。GPSエミュレーター内の地図は日本語対応ですが、残念ながら、執筆時点では、Mapコントロールの地図は日本語に対応しておりません。GPSエミュレーターの「Live」モードをオン(クリックすると背景がグレーになる)にして、右端の「seconds」矢印をクリックすると、1秒ごとにピンからピンに座標が変化します。

3

図6:マップ上のピンの位置の緯度と経度が表示され、エミュレーター内のMapにもピンが表示される。「Live」モードをオンにし、右端の「seconds」矢印をクリックすると、1秒ごとにピンからピンに座標が変化する(クリックで拡大)

サンプル一式は、会員限定特典としてダウンロードできます。記事末尾をご確認ください。
※サンプル実行でエラーが発生した場合は、「ソリューションのビルド」を実行後、再度、デバッグ開始を行ってください。

プロジェクトの作成

VS 2010のメニューから[ファイル(F)/新規作成(N)/プロジェクト(P)]を選択します。次に、「Windows Phone Application」を選択して、「名前(N)」に任意のプロジェクト名を指定します。ここでは「WP7_GPS」という名前を付けています。Windows Phoneのバージョンには7.0を選択します。

VS2010メニューの「プロジェクト(P)/参照の追加(R)」と選択してSystem.Deviceを追加しておいてください。

MainPage.xamlの編集とコントロールの追加

x:NameがPageTitleというTextBlockのTextプロパティに「位置情報の取得」と指定します。ツールボックスからMapコントロールを1個配置します。「第5回:パノラマページを作成する(前編)」で取得した、Bing Map Keyを指定して、リスト9のようにMainPage.xamlの要素に変更を加えてください。

リスト9 MapにBing Maps Keyを指定する(MainPage.xaml)

  <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <my:Map Height="601" HorizontalAlignment="Left" Margin="14,15,0,0" Name="Map1" VerticalAlignment="Top" Width="430">
      <my:Map.CredentialsProvider>
        <my:ApplicationIdCredentialsProvider ApplicationId="取得したBing Maps Keyを記述する" />
      </my:Map.CredentialsProvider>
    </my:Map>
  </Grid>

次に、ソリューションエクスプローラー内のMainPage.xamlを展開し、表示されるMainPage.xaml.vbをダブルクリックしてリスト10のロジックコードを記述します。

ロジックコードを記述する

リスト10 (MainPage.xaml.vb)

Option Strict On

単一のAPI を使用して、コンピューターの場所に容易にアクセスできる機能を提供するクラスの含まれる、System.Device.Location名前空間をインポートします。
Imports System.Device.Location

Windows PhoneのためのBing Maps Silverlightクラスの含まれる、Microsoft.Phone.Controls.Maps名前空間をインポートしておきます。
Imports Microsoft.Phone.Controls.Maps

Partial Public Class MainPage
  Inherits PhoneApplicationPage
  ~コード略~

GeoCoordinateWatcherクラスの新しいインスタンスであるmyGeoCoordiWatcherメンバ変数を宣言します。
Dim myGeoCoordiWatcher As New GeoCoordinateWatcher

ページが読み込まれた時の処理

GeoCoordinateWatcherクラスは、緯度および経度の座標に基づく場所データを提供するクラスです。
AddHandlerメソッドでGPS の位置情報が変化すると発生する、PositionChangedイベントに、myPositionChangedイベントハンドラを追加します。myPositionChangedイベントは、別スレッドから呼び出されるためBeginInvokeメソッドで、非同期で処理を呼び出します。
Startメソッドで、GPS入力を開始します。
  Private Sub MainPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
  
  AddHandler myGeoCoordiWatcher.PositionChanged, Sub(geoSender As Object, geoE As GeoPositionChangedEventArgs(Of GeoCoordinate))
  
Deployment.Current.Dispatcher.BeginInvoke(Sub() myPositionChanged(geoE))
                                                      End Sub
    myGeoCoordiWatcher.Start()
  End Sub

非同期で呼び出される処理

緯度と経度を、引数である GeoPositionChangedEventArgs の 、Posiotion.Location.Latitude と Position.Location.Longitude から取得し、変数myLatitudeとmyLongitudeに格納しておきます。
  地図を移動させるには、MapのCenterプロパティ、GeoCoordinateメソッドに、ダブル型の変数myLatitudeとmyLongitudeの値を指定します。ZoomLevelプロパティに10を指定します。ZoomLevelプロパティを指定しないと地図が表示されませんので注意してください。
 PushPinクラスの新しいインスタンスmyPinオブジェクトを生成します。Locationプロパティに、GeoCoordinateメソッドを使って緯度と経度を指定します。Contentプロパティには文字列に変換した経度と緯度を、「-」で連結して指定します。ピン上に緯度と経度が表示されます。緯度と経度とContentの指定されたmyPinオブジェクトをAddメソッドでMapに追加します。これで、GPSエミュレーター内と同じ位置に、Mapコントロールにもピンが立ちます。
  Private Sub myPositionChanged(myPosition As GeoPositionChangedEventArgs(Of GeoCoordinate))
    Dim myLatitude As Double = myPosition.Position.Location.Latitude
    Dim myLongitude As Double = myPosition.Position.Location.Longitude
 
    Map1.Center = New GeoCoordinate(myLatitude, myLongitude)
    Map1.ZoomLevel = 10
 
    Dim myPin As New Pushpin
    myPin.Location = New GeoCoordinate(myLatitude, myLongitude)
    myPin.Content = myLatitude.ToString & "-" & myLongitude
    Map1.Children.Add(myPin) 
  End Sub
End Class

アプリケーション終了時の処理

StopメソッドでGPS入力を止めます。
  Private Sub MainPage_Unloaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
    myGeoCoordiWatcher.Stop()
    myGeoCoordiWatcher = Nothing
  End Sub
  • 「ContextMenuコントロールを使う、加速度センサー、GPSでの位置情報取得」サンプルプログラム_3

  • 「ContextMenuコントロールを使う、加速度センサー、GPSでの位置情報取得」サンプルプログラム_2

  • 「ContextMenuコントロールを使う、加速度センサー、GPSでの位置情報取得」サンプルプログラム_1

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています