Tailspin would like to capture the user’s location 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 7 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.
The developers at Tailspin also decided that it is more important to save the survey data quickly and reliably, and not to 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, they use the latest available location data to save 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.
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 Visual Studio solution for the Tailspin Surveys application from CodePlex (http://go.microsoft.com/fwlink/?LinkId=205602).
The ILocationService interface defines a single method, TryTo GetCurrentLocation, which returns a GeoCoordinate object that holds the location data. The LocationService class implements this interface.
The LocationService class uses the GeoCoordinateWatcher class from the Windows Phone 7 API to retrieve the current location from the phone. Tailspin does not require highly accurate location data in the Surveys application, so the LocationService class initializes the GeoCoordinateWatcher class using the default accuracy. This gives the phone the opportunity to reduce its power consumption and to return location data more quickly.
The GeoCoordinateWatcher class uses the StatusChanged event to notify the application when it has an available fix on the phone’s location.
The following code example shows how the application initializes the GeoCoordinateWatcher object, handles the StatusChanged event, collects the phone’s location, and then disposes of the Geo CoordinateWatcher object. To minimize your application’s power consumption, you should dispose of the GeoCoordinateWatcher instance as soon as you’ve got the location data you need.
C#
private readonly TimeSpan maximumAge = TimeSpan.FromMinutes(15);
private GeoCoordinate lastCoordinate = GeoCoordinate.Unknown;
private DateTime lastCoordinateTime;
private GeoCoordinateWatcher watcher;
…
private void InitializeWatcher()
{
this.watcher =
new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
this.watcher.Start(true);
if (this.watcher.Status == GeoPositionStatus.Initializing ||
this.watcher.Status == GeoPositionStatus.NoData)
{
this.watcher.StatusChanged += this.WatcherStatusChanged;
}
else
{
this.GetNewLocation();
}
}private void WatcherStatusChanged(
object sender, GeoPositionStatusChangedEventArgs e)
{
this.GetNewLocation();
}
private void GetNewLocation()
{
if (this.watcher != null)
{
var newCoordinate = this.watcher.Position.Location;
if (newCoordinate != GeoCoordinate.Unknown)
{
this.lastCoordinate = this.watcher.Position.Location;
this.lastCoordinateTime = DateTime.Now;
}
this.DisposeWatcher();
}
}private void DisposeWatcher()
{if (this.watcher != null)
{
var oldWatcher = this.watcher;
this.watcher = null;
oldWatcher.Stop();
oldWatcher.Dispose();
}
}
To minimize how often the application requests location data from the phone, the TryToGetCurrentLocation method only asks the phone for new location data if at least 15 minutes have passed since the previous request.
The following code example shows the TryToGetCurrentLocation method that returns location data if the user has given consent for Tailspin to use location data obtained from the phone.
C#
public GeoCoordinate TryToGetCurrentLocation()
{
if (!this.settingsStore.LocationServiceAllowed)
{
return GeoCoordinate.Unknown;
}
if (this.watcher == null)
{
if (this.maximumAge <
(DateTime.Now – this.lastCoordinateTime) ||
this.lastCoordinate == GeoCoordinate.Unknown)
{
this.InitializeWatcher();
}
}
return this.lastCoordinate;
}
For more information about using the Location Service on the Windows Phone 7 platform, see Appendix C, “Leveraging Device Capabilities.”