ContextMenuコントロールを使う、加速度センサー、GPSでの位置情報取得
加速度センサー
加速度センサーは、「端末の向き」や「重力の方向」を探知するセンサーで、現在端末が重力に対してどのような傾きになっているかを、数値として取得することができます。
このプログラムで実装する機能の動作を、下記に解説しておきます。
表示されたエミュレーターの右隅上にマウスカーソルを持っていくと、コントロールパネルが表示されます。[>>]アイコンをクリックすると、図5のように加速度センサーのエミュレーターが表示されます。表示されている●を操作することで、エミュレーターの端末の傾きが変化します。その値はX、Y、Zに表示されます。加速度センサーのエミュレーターの傾きに合わせて、表示されている「うどん」の画像の傾きも変化します。
図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(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秒ごとにピンからピンに座標が変化します。
図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