Friday 25 March 2011

WP7 Tutorial - part 3: Using Location

In this example the use of the location API is demonstrated. The API is a high level interface to geo location. How the location is determined (e.g. GPS, GSM cell information) is of no concern to the developer.

The basic approach is to create an instance of GeoCoordinateWatcher and register two callback functions: one for when the status changes and one for when the location changes. The program demonstrates how these call backs are set up and how from within those function the user interface is updated with the received information. If the status is changes, the program checks what the current status is, and shows this in the status line (textBlock8.Text). If the position is changed then the new position information (Position.Location.Longitude, Position.Location.Latitude) - and additional information such as Speed, Altitude, Course, Accuracy are shown.

As an exercise you can build an application that shows you how close you are to a given target. In two input fields you enter the longitude and latitude of the destination (e.g. a geo cache location). And then you can calculate the difference from the current position to the target location and visualize or sonify the distance.

There is another example (Geo coordinate watcher) how to use this API on the Microsoft msdn website. In C. Petzold's book there is also a good example, see page 91ff.

See below the c# example using geo location on a windows phone 7. You can also download the geolocation project directory in a single ZIP-file.

using System;
using System.Collections.Generic;
using System.Windows;
using Microsoft.Phone.Controls;
using System.Device;
using System.Device.Location;

// the example shows the basic functionality of the location device
// you need to add in the solution explorer a reference to System.Device
// right click on References in the solution explorer, click Add Reference, and then
// System.Device
// Albrecht Schmidt, University of Stuttgart

// for a more comprehensive example see:
// http://msdn.microsoft.com/en-us/library/system.device.location.geocoordinatewatcher.aspx
// http://msdn.microsoft.com/en-us/library/ff431744(v=vs.92).aspx
// and page 91ff, C. Petzold, Programming Windows Phone 7

namespace Geo_Location
{
public partial class MainPage : PhoneApplicationPage
{
GeoCoordinateWatcher watcher;

// Constructor
public MainPage()
{
InitializeComponent();
}

// the initialize and start button is pressed
private void button1_Click(object sender, RoutedEventArgs e)
{
// initialize the geo watcher with defaul accuracy (battery saving)
// user GeoPositionAccuracy.High for higher accuracy
watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
// set movement threhold - as distance in meters - default is 0
watcher.MovementThreshold = 10;

// add a handler that is called when position is changed more than MovementThreshold
watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
// a handler for status change
watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);

// Start reading location data
watcher.Start();
}

void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
// you cannot change the UI in this function -> you have to call the UI Thread
Deployment.Current.Dispatcher.BeginInvoke(() => ChangeStatusUI(e));
}

void ChangeStatusUI(GeoPositionStatusChangedEventArgs e)
{
String statusType="";
if ((e.Status) == GeoPositionStatus.Disabled)
{
statusType = "GeoPositionStatus.Disabled";
}
if ((e.Status) == GeoPositionStatus.Initializing)
{
statusType = "GeoPositionStatus.Initializing";
}
if ((e.Status) == GeoPositionStatus.NoData)
{
statusType = "GeoPositionStatus.NoData";
}
if ((e.Status) == GeoPositionStatus.Ready)
{
statusType = "GeoPositionStatus.Ready";
}
textBlock8.Text = statusType;
}

void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
// you cannot change the UI in this function -> you have to call the UI Thread
Deployment.Current.Dispatcher.BeginInvoke(() => ChangeUI(e));
}

void ChangeUI(GeoPositionChangedEventArgs<GeoCoordinate> e)
{
textBlock1.Text = "Longitute: " + e.Position.Location.Longitude;
textBlock2.Text = "Latitute: " + e.Position.Location.Latitude;
textBlock3.Text = "Speed: " + e.Position.Location.Speed;
textBlock4.Text = "Altitude: " + e.Position.Location.Altitude;
textBlock5.Text = "Course: " + e.Position.Location.Course;
textBlock6.Text = "Vertical Accuracy: " + e.Position.Location.VerticalAccuracy;
textBlock7.Text = "Horizontal Accuracy: " + e.Position.Location.HorizontalAccuracy;
textBlock8.Text = "location updated at " + System.DateTime.Now.ToString("HH:mm:ss");
}

// the stop button clicked ... stop the watcher
private void button2_Click(object sender, RoutedEventArgs e)
{
if (watcher != null) { watcher.Stop(); }
textBlock8.Text = "location reading stopped";
}
}
}