Geoposition advanced tracking scenarios for Windows Phone 8

Geoposition advanced tracking scenarios for Windows Phone 8

  • Comments 9
  • Likes

This blog post was authored by Daniel Estrada Alva, a software development engineer on the Windows Phone team.

- Adam


Windows Phone 8 offers a new model for tracking a device’s position, based on change of distance, with the new Geolocator object. With this new model, the Geolocator object provides location updates at a defined time interval. This new functionality in Windows Phone 8 is different from tracking in Windows Phone 7, which uses an API that’s exposed through the MovementThreshold property to track device location.

The Geolocator object gives you more flexibility as you design your app by delegating most of the tracking logic to the Geolocator. Apps that require the acquisition of positions at a consistent time interval can now let the Geolocator handle the logic for them.

Choosing between ReportInterval and MovementThreshold

You can choose which model to use in your app to track a device’s position based on your needs. For example, if your app uses a very small movement threshold, the app could work better by defining a ReportInterval property.

Similarly, if the app defines a report interval to identify when the device moves a given distance or outside certain bounds, you should consider using the MovementThreshold property.

The following example illustrates how to use ReportInterval property:

Code Snippet
  1. public void StartTracking()
  2. {
  3.     if (this.trackingGeolocator!= null)
  4.     {
  5.         return;
  6.     }
  7.  
  8.     this.trackingGeolocator = new Geolocator();
  9.     this.trackingGeolocator.ReportInterval = (uint)TimeSpan.FromSeconds(30).TotalMilliseconds;
  10.  
  11.     if (this.positionChangedHandler != null)
  12.     {
  13.         this.positionChangedHandler = (geolocator, eventArgs) =>
  14.             {
  15.                 //...
  16.             };
  17.     }
  18.  
  19.     // this implicitly starts the tracking operation
  20.     this.trackingGeolocator.PositionChanged += positionChangedHandler;
  21. }

Similarly, the following example illustrates how to use MovementThreshold property:

Code Snippet
  1. public void StartTracking()
  2. {
  3.     if (this.trackingGeolocator!= null)
  4.     {
  5.         return;
  6.     }
  7.  
  8.     this.trackingGeolocator = new Geolocator();
  9.     this.trackingGeolocator.MovementThreshold = 100; // in meters
  10.  
  11.     if (this.positionChangedHandler != null)
  12.     {
  13.         this.positionChangedHandler = (geolocator, eventArgs) =>
  14.             {
  15.                 // ...
  16.             };
  17.  
  18.         // this implicitly starts the tracking operation
  19.         this.trackingGeolocator.PositionChanged += positionChangedHandler;
  20.     }
  21. }

Please note that the Geolocator does not define a MovementThreshold or ReportInterval by default; both properties are set to zero. You must explicitly choose between these two properties by setting one of them.

If you don’t set either of the properties, the operation to set an event handler for either the PositionChanged event or the StatusChanged event will throw a first-chance exception that can be captured by the Visual Studio 2012 debugger. Rather than simply catching this exception, you should fix the problem. If your app takes these parameters from user input, please remember that setting the properties to zero is equivalent to leaving them “unset” and will result in an exception.

The MovementThreshold always takes precedence over ReportInterval. If both properties are set, the events will be triggered based on the MovementThreshold. The ReportInterval will be ignored.

Working with the tracking events

Two events provide position data and status feedback back to the app. The first event, PositionChanged, provides the most up-to-date Geoposition object that matches the requirements of the request. The second event, StatusChanged, provides the current status of the request. It’s important for an app that uses location-tracking sessions to subscribe to the StatusChanged event to identify error conditions.

Registering for both events is quite similar, and you can see examples in all the code snippets in this post.

The StatusChanged event provides the new status using the PositionStatus enumeration.

Note: The StatusChanged event is not available for single Geoposition requests.

Apps also can poll for current status through the LocationStatus property. You can use this alternative method, for example, to check whether the user turned the Location on or off, and whether to display a message or fall back to asking the user for their current location.

Request lifetime

The Geolocator uses an asynchronous pattern for tracking operations. However, it does not provide explicit methods in the interface to start and stop the tracking request. The Geolocator keeps track of the event handlers that are registered. It implicitly starts tracking when event handlers are registered, and stops when all event handlers have been unregistered.

The very first event handler that is registered with the Geolocator on either of the events (PositionChanged or StatusChanged) will start the tracking operation. Similarly, when the last event handler is removed (PositionChanged or StatusChanged), the Geolocator will stop the tracking operation.

With this model the app can concentrate on registering and unregistering event handlers when it needs notifications; it leaves the responsibility of managing the state of the operation to the Geolocator. On the other hand, it requires the app to be careful about when event handlers are registered and unregistered to avoid wasting power.

Registering the events should be deferred until the time notifications are needed. For example, apps should not register the event handlers on app load (if the notifications are not needed as soon as the app loads). Similarly, leaving event handlers registered when the app doesn’t need more notifications also wastes power.

Another important remark in this regard is that the Geolocator does not implement a dispose mechanism. Apps are expected to unregister all event handlers before they release the reference to the Geolocator.

The following code snippet shows how an app can use the event handlers correctly:

Code Snippet
  1. private Geolocator trackingGeolocator;
  2. private TypedEventHandler<Geolocator, PositionChangedEventArgs> positionChangedHandler;
  3. private TypedEventHandler<Geolocator, StatusChangedEventArgs> statusChangedHandler;
  4.  
  5. public void StartTracking()
  6. {
  7.     if (this.trackingGeolocator!= null)
  8.     {
  9.         return;
  10.     }
  11.  
  12.     this.trackingGeolocator = new Geolocator();
  13.     this.trackingGeolocator.ReportInterval = (uint)TimeSpan.FromSeconds(30).TotalMilliseconds;
  14.  
  15.     if (this.positionChangedHandler != null)
  16.     {
  17.         this.positionChangedHandler = (geolocator, eventArgs) =>
  18.             {
  19.                 // ...
  20.             };
  21.     }
  22.  
  23.     if (this.statusChangedHandler != null)
  24.     {
  25.         this.statusChangedHandler = (geolocator, eventArgs) =>
  26.             {
  27.                 // ...
  28.             };
  29.     }
  30.  
  31.     // this implicitly starts the tracking operation
  32.     this.trackingGeolocator.StatusChanged += this.statusChangedHandler;
  33.     this.trackingGeolocator.PositionChanged += this.positionChangedHandler;
  34. }
  35.  
  36. public void StopTracking()
  37. {
  38.     if (this.trackingGeolocator == null)
  39.     {
  40.         return;
  41.     }
  42.  
  43.     this.trackingGeolocator.StatusChanged -= this.statusChangedHandler;
  44.     this.trackingGeolocator.PositionChanged -= this.positionChangedHandler;
  45.  
  46.     this.trackingGeolocator = null;
  47. }
The app can’t change the DesiredAccuracy, or transition between MovementThreshold and ReportInterval while tracking is in progress. The Geolocator object can be reconfigured after all the event handlers are unregistered.

Error conditions

The Geolocator will always try to honor the DesiredAccuracy requested by the app within the limits of the technologies used internally. A “best effort” approach is used, so in some circumstances the accuracy of the position may be lower than what the app desires. Although this is simpler for single Geoposition requests, it’s worth a more detailed discussion for tracking operations with MovementThreshold or ReportInterval.

When a tracking request is first started, the platform may need some time to achieve the accuracy requested, and it will trigger multiple events with progressively increasing accuracies at a rate higher than ReportInterval. For example, during a “warmup” period for a request with a DesiredAccuracy of 50 meters and a ReportInterval of 30 seconds, the app could be notified more than once during the first 30 seconds, and will get Geopositions with a progressively increasing accuracy until the DesiredAccuracy is achieved. After that happens, the Geolocator will notify the app only when the information matches the parameters specified by MovementThreshold or ReportInterval.

A second case to consider is when the Geolocator temporarily loses the ability to acquire Geoposition information. This can happen when the device initiates a high-accuracy tracking session based on GPS, and subsequently enters a region where GPS can’t get a good satellite signal. Although the platform attempts to obtain position from other sources, there will be some periods of time when the position update rate is affected.

If the Geolocator entirely loses the ability to acquire Geoposition, it notifies the app of this error status. When the Geolocator enters an error condition, the app won’t receive Geoposition notifications until the Geolocator again starts to acquire data. This is another reason why it’s important for apps to register for status notifications; they can show appropriate UI during such error conditions.

When the Geolocator recovers from an error state, it sends the app a status notification with the new status. After this, the app can expect Geoposition notifications to start arriving again. Keep in mind that if the Geolocator was in an error state for a long time, there may be a “warmup” period as described previously in this post.

The following diagram describes the transition between various statuses for the Geolocator:

  image

Note that when the Geolocator reaches the Ready state based on the PositionStatus enumeration, the app doesn’t send a status notification with the same state every time a Geoposition is available. The app only receives a status update when the status changes.

I hope you’ve found the information in this post useful, and that it will help you write great location-aware apps for Windows Phone 8.

9 Comments
You must be logged in to comment. Sign in or Join Now
  • Thanks for the blog post.

    In one of my Windows Phone 8 apps, I found a specific case that the _geolocator.GetGeopositionAsync never return even if a time out was specified as a argument.

    My app uses the MapExtensions from the Windows Phone Toolkit and has many push pin that are setup during the load of the app.

    If you are facing a similar problem with GetGeopositionAync not returning, use the following code:

           public Task GetCurrentPosition()

           {

               return Task.Run(() =>

               {

                   if (_geolocator == null)

                   {

                       _geolocator = new Geolocator { DesiredAccuracy = PositionAccuracy.High };

                   }

                   Geoposition geoposition = null;

                   ManualResetEvent syncEvent = new ManualResetEvent(initialState: false);

                   IAsyncOperation asyncOp = _geolocator.GetGeopositionAsync();

                   asyncOp.Completed += (asyncInfo, asyncStatus) =>

                       {

                           if (asyncStatus == AsyncStatus.Completed)

                           {

                               geoposition = asyncInfo.GetResults();

                           }

                           syncEvent.Set();

                       };

                   syncEvent.WaitOne();

                   return geoposition.Coordinate;

               });

           }

    ArchieCoder

  • Hi all,

    I think samples are not correct.

    The line : if (this.positionChangedHandler != null)

    should be replaced by : if (this.positionChangedHandler == null)

    And the line : if (this.statusChangedHandler != null)

    should be replaced by : if (this.statusChangedHandler == null)

  • mvadu
    8 Posts

    That's good news.. I don't care if there aren't any apps to suite my needs. I can write my own. Now my wait  for Lumia 920 continues..:(

  • Navigation and Geo-Tracking Apps are now an exception in that they can keep running in the background - not only under the lockscreen. But only one of those Apps can run at a time (e.g. you can't run Navigon and Runtastic at the same time) and the Apps have to support the feature which means it only works with WP8 versions of an App.

    I can't tell you if there currently are Apps that support your use case in the marketplace.

  • mvadu
    8 Posts

    Either way.. to be any use for a photographer on a hike as a geo tagging tool, it need to log the geolocation at least once every minute. In WP7.5 background scheduler was allowed to run only once every 30 minutes, which was not useful. Even if it were to run under lock screen as soon as I switch to start screen it would be tomb stoned, and wont log anything. Is it the same situation in WP8 too?

    Note: I am waiting for my Lumina 920 to show up in mail. Due to Nokia's inability to judge the demand its been out of stock for quite sometime now. So I am not able to run these things on a device. With my old laptop I don't think I can run the WP8 emulator. WP7.5 emulator runs in software mode.

  • I'm sorry, while screen locked or from background scheduler. In WP 7.5 Background Scheduler used to return cached result, that's now fixed in WP8.

  • mvadu

    Yes it can perform monitoring behind the scene. i.e. while unlocked.

  • mvadu
    8 Posts

    Do we get these notifications even when my app is not the foreground app? I am looking to replace my geologger (used to geo tag my pictures from DSLR) with my smartphone. WP7.5 disappointed me in this area since the notifications stopped as soon as my app lost focus. Does things get any better in WP8? If not why? IOS and Android both have nice geo tracking/logging apps, windows phone wont due to platform limitations.

  • So the MovementThreshold is great for notifying you of when you leave a certain radius from your current position. How would you suggest handling the situation where you want to be notified when you *enter* a given radius from a specified position (say, if you get within 100m of your favorite coffee shop)?

    Thanks!