Quality Assurance Analyst, Windows Phone developer and father. Contributing author for Windows Phone 8 in Action from Manning Publications. Adam is a DZone MVB and is not an employee of DZone and has posted 15 posts at DZone. You can read more from them at their website. View Full User Profile

Windows Phone 8 and Continuous Location Tracking in the Background (Pt.2)

08.15.2012
| 2111 views |
  • submit to reddit

The first article talked about how to use the new Location API on Windows Phone 8. In it, I did not talk about background tracking. Today I will modify the prior solution to do that and to log events to the output window as well as prevent the UI from being updated while the app is deactivated.

Source is available here.

We will start with telling the OS that this app can track location in the background. First thing is to open the WMAppManifest.xml file in the XML editor by right-clicking it and selecting Open With.

Now we replace the DefaultTask element with the following:

<DefaultTask Name="_default" NavigationPage="MainPage.xaml">
  <BackgroundExecution>
    <ExecutionType Name="LocationTracking" />
  </BackgroundExecution>
</DefaultTask>

Next we add an event handler for the RunningInBackground event. In theApp.xaml file, update the shell:PhoneApplicationService element by adding RunningInBackground=”Application_RunningInBackground” so it looks like this:

<shell:PhoneApplicationService
    Launching="Application_Launching" Closing="Application_Closing"
    Activated="Application_Activated" Deactivated="Application_Deactivated"
    RunningInBackground="Application_RunningInBackground"/>

And add an empty handler to App.xaml. We will come back to this handler in a bit.

private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args)
{
}

We need a way to tell the app that it is running in the background. To the App.xaml.cs we need to add a bool property. It will be set to static so it is easily addressed:

public static bool InBackground { get; set; }

Now we will add the ability to view the state of the app in the debug window. To do this we need to add the following using to the App.xaml.cs and MainPage.xaml.cs pages:

using System.Diagnostics;

With that added, we can start updating the following 4 events with the following App.InBackground values:

Handler App.InBackground
Application_Launching false
Application_Activated false
Application_Deactivated true
Application_RunningInBackground true

As we set those, we will also add a Debug.WriteLine to each as well so we can see when they fire. Once done, they should look like this:

// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
    Debug.WriteLine("Application Launching.");
    App.InBackground = false;
}
 
// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
    Debug.WriteLine("Application Activated.");
    App.InBackground = false;
}
 
// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
    Debug.WriteLine("Application Deactivated.");
    App.InBackground = true;
}
 
private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args)
{
    Debug.WriteLine("Running in background.");
    App.InBackground = true;
}

As you can see, we are simply setting a flag to indicate if the app is running in the background. There may be a baked in way of doing this but I have done it this way.

With this in place, we can now update the geolocator_PositionChanged event handler in the MainPage.xaml.cs file to log the location in the Debug window.

Debug.WriteLine(args.Position.Coordinate.Latitude.ToString("0.00000000") + " " + args.Position.Coordinate.Longitude.ToString("0.00000000"));

The final update is to use the App.InBackground property in an if statement to turn off UI updating. We use Debug.WriteLine to tell us the location in the Debug window.

if (App.InBackground == false)
{
    Dispatcher.BeginInvoke(() =>
    {
        Debug.WriteLine("UI Updated.");
        LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00000000");
        LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00000000");
    });
}
else
{
    Debug.WriteLine("UI NOT Updated.");
}

Now we can run the solution and we see in the debug window (in the bottom left corner) the Application Launching event firing:

Clicking the button starts tracking and the UI is updated and the location is written to the debug window:

Clicking map locations in the emulator will update the UI and log the location:

Now if we click the Start button, we see the app switch to a background task and is logged as “Running in Background”. Clicking map locations, shows the location is still being logged but the UI is not being updated:

Reopening the app show the Application Activated event fire and the clicking new map locations is updating the UI again:

And finally, exiting the app using the back button fires the Application Closing event and clicking new map locations are no longer being logged as the app is no longer running in the background:

There are best practices you need to use when implementing any battery intensive operations and location services are no different. Setting the DesiredAccuracy property of the Geolocator object to PositionAccuracy.Default instead of PositionAccuracy.High and turning off Location Service when not needed will save battery. Increasing the MovementThreshold property will cause the PositionChanged event to fire less often will also save battery.

Another thing to keep in mind to plan for some or all Location Services may not be available and your application should handle this situation without throwing exceptions.

As you see, continuously tracking a handset location in real time with the application in the background is simple to implement in Windows Phone 8 applications.

 

 

 

Published at DZone with permission of Adam Benoit, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)