Windows Phone 7 physical devices contain features that allow the device to determine its geographical position in terms of latitude and longitude. The data is obtained through a combination of the built-in Global Positioning System (GPS) feature, the location of cellular phone stations that the device is communicating with, and information obtained from Wi-Fi connections. It also contains a control that you can use to display a map in your application.
When using the Location Service in an application, you should be aware of the following factors:
- Location data may not be available at all times.
- The accuracy depends on the types of information available from the sensors, and on the settings you specify for the Location Service.
- Using the Location Service, especially when you specify high accuracy, consumes additional power and more quickly drains the device’s battery.
- Initializing and obtaining the first reading when the Location Service is started may take up to a minute.
- The user must give his permission for code to access location information. If the user has disabled the Location Service, your application must be able to operate without location information or warn the user that it cannot run unless he enables the Location Service.
Good practice for using the Location Service is to turn it on only when required, and turn it off as soon as is practical. Also consider using the lower accuracy, power-optimized setting unless your application absolutely requires higher accuracy. For example, you may only want to know the city or region where the device is located.
You can use the Location Service in two ways. You can set it running asynchronously and obtain position readings from the callback handlers attached to the GeoCoordinateWatcher instance when data becomes available. Alternatively, you can start the Geo CoordinateWatcher instance synchronously so that your code will wait until the first reading is obtained, or until the process times out after a specified interval.
To use the Location Service, you must do the following:
- Add a reference to the assembly System.Device to your project. The classes you will use are in the System.Device.Location namespace.
- Instantiate a GeoCoordinateWatcher.
- Specify the properties for the GeoCoordinateWatcher.
- Optionally specify callbacks in the form of event handlers or lambda expressions that will receive the data if you are using the service asynchronously.
- Start the GeoCoordinateWatcher.
Asynchronous Location Service Operation
The following code example creates and starts a GeoCoordinate Watcher instance asynchronously.
C#
// Create a GeoCoordinateWatcher and specify the accuracy required.
// Use GeoPositionAccuracy.Default unless high accuracy required.
GeoCoordinateWatcher watcher =
new GeoCoordinateWatcher(GeoPositionAccuracy.High);
// Check if the user has provided permission to use the service.
if (watcher.Permission == GeoPositionPermission.Denied)
{
// Permission to use Service Location denied by user.
}
else
{
// Set movement threshold in meters.
// Use at least 20 to avoid excessive
// change events generated by minor changes
// in environment or signal quality.
// Higher values also help to maximize battery
// life for the device.
watcher.MovementThreshold = 30;
// Add handlers for StatusChanged and PositionChanged events.
watcher.StatusChanged
+= new EventHandler<GeoPositionStatusChangedEventArgs>
(Watcher_StatusChanged);
watcher.PositionChanged
+= new EventHandler<GeoPositionChangedEventArgs
<GeoCoordinate>>(Watcher_PositionChanged);
// Start data acquisition.
watcher.Start();
}
The StatusChanged event handler can detect if the watcher service is ready and contains data, allowing you to display a corresponding message to the user and interact with the service in your application code as required. The value is one of the GeoPositionStatus enumeration values: Ready, Disabled, Initializing, and NoData.
C#
void Watcher_StatusChanged(object sender, GeoPositionStatus
ChangedEventArgs e)
{
string currentStatus = e.Status.ToString();
}
Remember that the event handlers run on a different thread from the UI, so you must invoke a method on the UI thread if you want to update the UI with the discovered values.
The PositionChanged event handler is executed each time a position change greater than that defined for the MovementThreshold property occurs. It receives an instance of the GeoCoordinate class that contains the current location information.
C#
void Watcher_PositionChanged(object sender,
GeoPositionChangedEventArgs
<GeoCoordinate> e)
{
// Check to see if location data is available.
if (e.Position.Location.IsUnknown)
{
// Data is not available
}
else
{
double latitude = e.Position.Location.Latitude;
double longitude = e.Position.Location.Longitude;
double altitude = e.Position.Location.Altitude;
double course = e.Position.Location.Course;
double speed = e.Position.Location.Speed;
double hAccuracy = e.Position.Location.HorizontalAccuracy;
double vAccuracy = e.Position.Location.VerticalAccuracy;
DateTimeOffset time = e.Position.Timestamp;
}
}
Note that some values may not be available (NaN) depending on the current location method in use and the specified accuracy. When you no longer need to obtain location information, you should preserve battery life by stopping the watcher. To do this, call the Stop method.
Synchronous Location Service Operation
If you want your code to wait for the first position value to be available from the service, or if you just want to obtain a single position value, use the TryStart method and specify a timeout value. The first parameter of this method should be set to true in this release of the service. The GeoCoordinateWatcher class exposes the Status property, which is one of the GeoPositionStatus enumeration values. If the status is Ready, you can check for and retrieve the data exposed by the service from the Position property of the watcher.
C#
GeoCoordinateWatcher watcher = new GeoCoordinateWatcher
(GeoPositionAccuracy.High);
watcher.TryStart(true, TimeSpan.FromSeconds(60));
// Check to see if location data is available.
if (watcher.Status == GeoPositionStatus.Ready
&& !watcher.Position.Location.IsUnknown)
{
double latitude = watcher.Position.Location.Latitude;
double longitude = watcher.Position.Location.Longitude;
double altitude = watcher.Position.Location.Altitude;
double course = watcher.Position.Location.Course;
double speed = watcher.Position.Location.Speed;
double hAccuracy = watcher.Position.Location.HorizontalAccuracy;
double vAccuracy = watcher.Position.Location.VerticalAccuracy;
DateTimeOffset time = watcher.Position.Timestamp;
}
else
{
// Data is not available.
}
watcher.Stop();
Note that some values may not be available (NaN) depending on the current location method in use and the specified accuracy.
For more information, see “Location for Windows Phone” on MSDN (http://msdn.microsoft.com/en-us/library/ff431803(VS.92).aspx). You can also download a code sample that demonstrates using the Location Service from “Code Samples for Windows Phone” on MSDN (http://msdn.microsoft.com/en-us/library/ff431744(VS.92).aspx).
Using Location Information and Displaying a Map
Location information provides only the coordinates of the device. You can subscribe to a mapping service or use helper routines to convert the coordinates into a street-level address or other format more suited to your requirements.
If you simply want to display a map, you can use the web browser on the device to open a mapping site at the appropriate location. For example, the following code opens the Bing™ Maps website using the latitude and longitude values. To use this code, you must add a reference to the System.Text namespace.
C#
StringBuilder mapUrl = new StringBuilder(
“http://www.bing.com/maps/default.aspx?lvl=15&style=r&v=2&cp=”);
aspx?lvl=15&style=r&v=2&cp=”);
mapUrl.Append(latitude.ToString());
mapUrl.Append(“~”);
mapUrl.Append(longitude.ToString());
WebBrowserTask webTask = new WebBrowserTask();
webTask.URL = mapUrl.ToString();
webTask.Show();