Getting the location on Windows Phone is done via the GeoCoordinateWatcher. The coordinate watcher has some best practices associated with it one of which is to minimize power consumption. Once you turn this thing on, it's going to be using the GPS to stream location event back to your app which will hit the battery.
There are some instances where you may note a running notification of the current portion but just want the current position (for instance, you may want to initialize the position on a map but not track changes to position).
So this is a small helper class that starts up the coordinate watcher asynchronously, returns the first coordinate found and then shuts it down. One could use TryStart like so:
using (var watcher = new
GeoCoordinateWatcher(GeoPositionAccuracy.Default))
{
var location = watcher.TryStart
(false, TimeSpan.FromMilliseconds(1000));
}
but since that will block your UI thread (assuming you call it from the UI) you'd need to wrap it in some asynchronous stuff anyways.
So I use this class:
public class ImmediateLocation : IDisposable
{
private GeoCoordinateWatcher _watcher;
private Action<GeoCoordinate> _action;
public ImmediateLocation(Action<GeoCoordinate> a)
{
Debug.Assert(a != null);
_action = a;
}
public void GetLocation()
{
if (_watcher == null)
{
_watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
_watcher.MovementThreshold = 1000;
_watcher.PositionChanged += new
EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>
(_watcher_PositionChanged);
_watcher.StatusChanged += new
EventHandler<GeoPositionStatusChangedEventArgs>
(_watcher_StatusChanged);
_watcher.Start(false);
if (_watcher.Status == GeoPositionStatus.Disabled
|| _watcher.Permission == GeoPositionPermission.Denied)
Dispose();
}
}
void _watcher_StatusChanged(object sender,
GeoPositionStatusChangedEventArgs e)
{
if (e.Status == GeoPositionStatus.Disabled
|| _watcher.Permission == GeoPositionPermission.Denied)
Dispose();
}
void _watcher_PositionChanged(object sender,
GeoPositionChangedEventArgs<GeoCoordinate> e)
{
_action(e.Position.Location);
Dispose();
}
public void Dispose()
{
if (_watcher != null)
{
_watcher.Stop();
_watcher.PositionChanged -= new
EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>
(_watcher_PositionChanged);
_watcher.StatusChanged -= new
EventHandler<GeoPositionStatusChangedEventArgs>
(_watcher_StatusChanged);
_watcher.Dispose();
}
_watcher = null;
_action = null;
}
}
Then you can just do this:
var immediate = new ImmediateLocation(x => location = x);
immediate.GetLocation();
GeoCoordinate location;
It acts like a one time use, fire and forget location setter that cleans itself up when done. It does have Dispose
if you want to manage the lifetime more closely.
CodeProject