Using the Location Service
One popular component of mapping applications is some type of reference to the current location of the application's user, whether to show location on a map or to use the location as input to other requests. Windows Phones have a Location Service that provides information about the location of the device.
You can access location information through the GeoCoordinateWatcher class, which is in the System.Device.Location namespace in the System.Device assembly. This class provides access to the Location Service, including the device's position, changes to that position, status of the Location Service, and the ability to stop and start the Location Service. In applications built using the ArcGIS API for Windows Phone, you have two options for working with the position of the device: use the GPSLayer to easily get the location displayed on the map, or access device location directly.
This topic includes tips for working with the Location Service. However, before working with the Location Service, the following topics from Microsoft are recommended:
Using the GPSLayer
In the ESRI.ArcGIS.Client.Toolkit.DataSources assembly, a GpsLayer class is provided. This layer is a specialized version of the GraphicsLayer, designed to facilitate showing location on the map and handle interfacing with the Location Service for you. You can add it as a layer in the Map element in the XAML and also interact with it in the code-behind. Using this layer type, you can create an application that shows location on a map by taking the following steps.
See the GPS sample in the Toolkit Data Sources section of the Interactive SDK for an example of using the GpsLayer. This sample is only available in the downloaded version of the samples (and not in the viewer on the website) since it requires the device's Location Service.
- Create a new solution and add a map to your page. Your application should match the one created in Creating a map, but don't set an extent on the Map element in the XAML.
- Add a reference to the ESRI.ArcGIS.Client.Toolkit.DataSources assembly.
- In the MainPage.xaml file, add the following namespace definition:
xmlns:esriDS="clr-namespace:ESRI.ArcGIS.Client.Toolkit.DataSources;assembly=ESRI.ArcGIS.Client.Toolkit.DataSources"
- While still in the MainPage.xaml file, browse to the Map element, and add a GpsLayer to it so that it matches the following code:
<esri:Map x:Name="MyMap"> <esri:Map.Layers> <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer" Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"> </esri:ArcGISTiledMapServiceLayer> <esriDS:GpsLayer x:Name="myGpsLayer" /> </esri:Map.Layers> </esri:Map>
Caution:If your map has a spatial reference other than WGS84 or Web Mercator, you need to provide a Geometry Service that the GpsLayer can use to reproject to the appropriate spatial reference. The location is returned in the WGS84 spatial reference, and client-side reprojection is used if it needs to be converted to Web Mercator. A Geometry Service is provided as shown in the following GpsLayer XAML definition:
<esriDS:GpsLayer x:Name="myGpsLayer" GeometryServiceUrl="http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer" />
- Run the application. If necessary, pan the map so that your location is visible on the screen. You can also zoom in to see exactly where you are.
In the previous steps, you didn't need to work with the Location Service directly. The GpsLayer handles the connection for you, and, by default, the GeoPositionWatcher property is tied to the System.Device.Location.GeoCoordinateWatcher with a request for a high accuracy location data. You can start and stop the Global Positioning System (GPS) tracking by using the IsEnabled property on the GpsLayer. The GpsLayer draws the last known location on the screen and provides access to that location using either the GeoCoordinate or Position property. The GeoCoordinate property contains the location in geographic coordinates, along with the current speed, altitude, horizontal and vertical accuracies, and course (also referred to as the heading). The Position property provides the location as a MapPoint in the spatial reference required by the map.
Although by default a GpsLayer connects to the phone's built-in System.Device.Location.GeoCoordinateWatcher, you can override this to hook your application to a simulator. See Simulating location in the emulator for details.
The GeoCoordinateChanged and PositionChanged events are also provided off the GpsLayer class. Although these both fire each time the current GPS location updates, the GeoCoordinateChanged event fires when the location updates, while the PositionChanged event fires after the GeoCoordinate is reprojected to the map's spatial reference.
The look and feel of the GpsLayer can be customized by setting properties available through the GpsLayer class. When you run the application created in the previous steps, you'll see a blue dot indicating your location, which can be customized by setting the LocationMarkerSymbol. The pale blue circle around the dot indicates the accuracy and can be customized by setting the AccuracyCircleSymbol. An occasional pulse is visible radiating out from the dot: this indicates updates are being received from the Location Service and can be turned on or off using the AnimatesUpdates property.
When working with the GpsLayer, you can also bind to properties to display their values. For example, if you want the top of your application to show the Location Service's status, you can add the following grid below the map in the XAML:
<Grid VerticalAlignment="Top" Background="{StaticResource PhoneSemitransparentBrush}"
Opacity="0.85" >
<TextBlock x:Name="StatusTextBlock"
Text="{Binding ElementName=MyMap, Path=Layers[1].GeoPositionWatcher.Status}"
Visibility="Visible" HorizontalAlignment="Center" TextWrapping="Wrap"
Margin="5,0,5,0" />
</Grid>
Accessing device location
If you need direct access to the location on a device, you can work directly with the Location Service. You'll need to start and stop the service, as well as handle setting up events for status and position changes. See How to: Get data from the Location Service for Windows Phone for details.
If you also want to display the information on the map, but do not want to use the GpsLayer, you can place a graphic into a GraphicsLayer contained in a map and update the X and Y of the graphic when the position updates.
The following code sections assume your project contains the following:
- References to the ESRI.ArcGIS.Client, System.Device, and System.Runtime.Serialization assemblies
- A MarkerSymbol RedMarkerSymbol
- A GeoCoordinateWatcher _watcher with its PositionChanged event hooked to watcher_PositionChanged
<esri:GraphicsLayer ID="MyGraphicsLayer">
<esri:GraphicsLayer.Graphics>
<esri:Graphic Symbol="{StaticResource RedMarkerSymbol}">
<esriGeometry:MapPoint X="NaN" Y="NaN" />
</esri:Graphic>
</esri:GraphicsLayer.Graphics>
</esri:GraphicsLayer>
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
ESRI.ArcGIS.Client.Projection.WebMercator mercator = new ESRI.ArcGIS.Client.Projection.WebMercator();
_graphicLocation.Geometry = mercator.FromGeographic(new MapPoint(e.Position.Location.Longitude, e.Position.Location.Latitude));
If your map doesn't have a spatial reference of Web Mercator, you'll need to take this into account when setting the geometry on your graphic. If it's in WGS84, use the e.Position values without any conversion. If it's in a different spatial reference, you'll need to use a geometry task to project your coordinates. See the Project section in the Geometry task topic.
See the Show GPS Location sample in the Device section of the Interactive SDK for an example of directly accessing the device's location.
This sample is only available in the downloaded version of the samples (and not in the viewer on the website) since it requires the device's Location Service.
Tips for working with the Location Service
Using the previous sections in this topic, it's easy to create an application that makes use of the phone's Location Service. However, keep in mind the following points when working with location:
- The Location Service uses a combination of GPS, Wi-Fi, and cellular sources to determine the location of the device, based on the developer request for higher accuracy data or the default lower accuracy, power-optimized setting. Use the default setting of lower accuracy, power-optimized location. Only request high accuracy location information if it's required (for example, in routing applications). High accuracy data is requested using the GeoCoordinateWatcher.DesiredAccuracy property. This can be set using the GeoPositionAccuracy enumeration value of High when the GeoCoordinateWatcher is defined, as shown in the following code:
GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
- Only have the Location Service on when you're requesting information from it. Stop it once you're done. The service is started and stopped using the Start and Stop methods on the GeoCoordinateWatcher class.
- Use the MovementThreshold property on the GeoCoordinateWatcher to control how often the Position updates, and as a result, how often the PositionChanged event will fire. A larger setting will lower battery consumption and help eliminate noise in the signal. If you're using the GpsLayer, you can set the movement threshold on the GeoPositionWatcher property in the XAML by using the following code:The movement threshold property can also be set on the GpsLayer in code-behind as follows (where myGpsLayer is a GpsLayer that has already been initialized):
<esriDS:GpsLayer.GeoPositionWatcher> <location:GeoCoordinateWatcher MovementThreshold="20" /> </esriDS:GpsLayer.GeoPositionWatcher>
(myGpsLayer.GeoPositionWatcher as GeoCoordinateWatcher).MovementThreshold = 20;
Caution:The GPS Emulator doesn't support the movement threshold, so if you're simulating location in the emulator, make sure this code is only executed if using the actual Location Service on the device.
- Plan for application behavior when location information is not available.