Using Location Services on the Phone

patterns & practices Developer Center

On this page: Download:
You Will Learn | Overview of the Solution | Inside the Implementation Download code samples
Download book as PDF

You Will Learn

  • How to capture and store location data.
  • How to minimize power consumption when capturing location data.

Tailspin would like to capture users locations when they are answering a survey and include this location information as part of the survey data that's sent to the Tailspin service when the synchronization process runs. Tenants can use the location information when they analyze the survey results.

Overview of the Solution

The Windows Phone API includes a Location Service that wraps the available hardware on the phone and enables your application to easily access location data. However, there is a trade-off between the accuracy of the data you can obtain from the Location Service and your application's power consumption. Tailspin does not require highly accurate location data for their surveys, so they have optimized the Surveys mobile client application to minimize power consumption.

Higher accuracy in location data requires higher power consumption.

The developers at Tailspin also decided that it is more important to save the survey data quickly and reliably, and not wait if the location data is not currently available. It can take up to 120 seconds to get location data back from the Location Service. Therefore, if the Location Service doesn't have the location data when the Tailspin mobile client application requests it, the latest available location data is saved along with the survey answers, instead of waiting for new data. Furthermore, the application only asks the Location Service for location data when the Surveys application needs it to save with a survey, although in some applications, you might consider caching the available location data at fixed intervals.

Note

The sample application asks the user's permission to collect location data in the AppSettingsView page. In your own application, you must obtain the user's consent before collecting and using location data, typically on an initial settings screen when the application first runs. You should also make sure that your application can continue to function if the user disables the Location Service or doesn't give their consent for your application to use the phone's location data.

Hh821018.note(en-us,PandP.10).gifMarkus Says:
Markus
                The Tailspin Surveys website displays survey location data using a BingĀ® search engine maps control. For more information, see the SuveyLocation.ascx file in the TailSpin.Web project. There is also a Bing maps control available for Windows Phone.</td>

Inside the Implementation

Now is a good time to walk through the code that acquires location data from the phone in more detail. As you go through this section, you may want to download the Windows Phone Tailspin Surveys application from the Microsoft Download Center.

The following code example shows the ILocationService interface from the TailSpin.PhoneServices project.

public interface ILocationService
{
  GeoCoordinate TryToGetCurrentLocation();
  void StartWatcher();
  void StopWatcher();
}

The TryToGetCurrentLocation method returns a GeoCoordinate object that holds the location data. The LocationService class implements this interface.

Hh821018.note(en-us,PandP.10).gifMarkus Says:
Markus You could also create a dummy implementation of the ILocationService interface that returns a fixed location to use in the emulator. Alternatively, you can simulate location data using the location sensor simulator in the emulator.

The LocationService class uses the GeoCoordinateWatcherAdapter class from the TailSpin.Phone.Adapters project to retrieve the current location from the phone when the user starts a survey and when the user completes a survey. The GeoCoordinateWatcherAdapter class implements the IGeoCoordinateWatcher interface and adapts the GeoCoordinateWatcher class from the Windows Phone API in order to create a loosely coupled class that is testable. Tailspin does not require highly accurate location data in the Surveys application, so the ContainerLocator class initializes the GeoCoordinateWatcherAdapter class using the default accuracy. This gives the phone the opportunity to reduce its power consumption and to return location data more quickly. The following code example shows the initialization of the GeoCoordinateWatcherAdapter class in the ContainerLocator class.

private void ConfigureContainer()
{
  ...
  this.Container.Register<IGeoCoordinateWatcher>(c => 
    new GeoCoordinateWatcherAdapter(GeoPositionAccuracy.Default));
  ...
}
Hh821018.note(en-us,PandP.10).gifChristine Says:
Christine It's up to the phone to determine the optimal way to obtain the phone's location: using the available data from the Global Positioning System (GPS) receiver, using cellular triangulation, or using Wi-Fi data.

The StatusChanged event in GeoCoordinateWatcherAdapter class indicates that the status of the GeoCoordinateWatcherAdapter object has changed. The status could be Ready, Initializing, NoData, or Disabled. The GeoCoordinateWatcherAdapter class uses the StatusChanged event to indicate the ability of the location provider to provide location updates. The following code example shows the TryToGetCurrentLocation, StartWatcher, and StopWatcher methods from the LocationService class.

private readonly TimeSpan maximumAge = TimeSpan.FromMinutes(15);
private GeoCoordinate lastCoordinate = GeoCoordinate.Unknown;
private DateTime lastCoordinateTime;
private IGeoCoordinateWatcher geoCoordinateWatcher;
...

public GeoCoordinate TryToGetCurrentLocation()
{
  if (!settingsStore.LocationServiceAllowed)
  {
    return GeoCoordinate.Unknown;
  }

  if (geoCoordinateWatcher.Status == GeoPositionStatus.Ready)
  {
    lastCoordinate = geoCoordinateWatcher.Position.Location;
    lastCoordinateTime = geoCoordinateWatcher.Position.Timestamp.DateTime;
    return lastCoordinate;
  }

  if (maximumAge < (DateTime.Now - lastCoordinateTime))
  {
    return GeoCoordinate.Unknown;
  }
  else
  {
    return lastCoordinate;
  }
}

public void StartWatcher()
{
  this.geoCoordinateWatcher.Start();
}

public void StopWatcher()
{
  this.geoCoordinateWatcher.Stop();
}

The TryToGetCurrentLocation method only returns location data if the user has given consent for Tailspin to use location data obtained from the phone; otherwise, GeoCoordinate.Unknown is returned. If the user has given consent for Tailspin to use location data, the location and the time the location was acquired are obtained from the GeoCoordinateWatcherAdapter class, provided that the Status property of the GeoCoordinateWatcherAdapter class is GeoPositionStatus.Ready. If the Status property of the GeoCoordinateWatcherAdapter class is not GeoPositionStatus.Ready, the method returns the last available location data, provided that it was obtained within the last 15 minutes. Otherwise, it returns GeoCoordinate.Unknown.

The StartWatcher and StopWatcher methods are used by the TakeSurveyViewModel class to initiate and stop the acquisition of data from the current location provider, respectively.

Next Topic | Previous Topic | Home

Last built: May 25, 2012