How to continuously track the phone's location for Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

This topic shows you how to use the Windows Phone Location APIs to continuously track the phone’s location. If your app only needs the user’s location at the current time, such as checking the user in at a location or making a location-based search, you should use the single-shot technique described in How to get the phone's current location for Windows Phone 8. Continuously tracking the user’s location drains the user’s battery more than getting a single location and should only be used for apps that require it.

Important Note:

To use the Location API in your Windows Phone app, you must include in the ID_CAP_LOCATION capability in your app manifest file. If you don’t do this your app will throw an exception when you deploy it during development and will cause your app to fail ingestion when you submit it to the Windows Phone Store. For more information, see App capabilities and hardware requirements for Windows Phone 8.

Tip

The Windows Runtime location API is supported for both Windows Phone 8 and Windows Phone 8.1 apps. This topic is part of the Windows Phone 8 documentation. To view the Windows Phone 8.1 documentation for this feature, which includes information on developing for both phone and PC, see Detecting Geolocation.

Continuously tracking the phone’s location

  1. Create a new Windows Phone app.

  2. In Solution Explorer, expand the Properties folder, and then double-click WMAppManifest.xml.

  3. On the Capabilities tab of the manifest designer, select the check box next to ID_CAP_LOCATION.

  4. In MainPage.xaml, paste the following XAML code over the existing Grid element named “ContentPanel”. This code defines a button that will initiate the location API and some text blocks to display latitude, longitude, and the app’s status.

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <StackPanel>
            <Button x:Name="TrackLocationButton" Click="TrackLocation_Click" Content="track location"/>
            <TextBlock x:Name="LatitudeTextBlock"/>
            <TextBlock x:Name="LongitudeTextBlock"/>
            <TextBlock x:Name="StatusTextBlock"/>
        </StackPanel>
    </Grid>
    
  5. In MainPage.xaml.cs, add the following using statements to the top of the file.

    using System.Threading.Tasks;
    using Windows.Devices.Geolocation;
    
  6. Inside the MainPage class definition, declare one variable for the Geolocator object, and one that will track whether the app is actively tracking location.

    Geolocator geolocator = null;
    bool tracking = false;
    
  7. Add a consent prompt to allow the user to opt out of allowing your app to access their location. All apps should obtain user consent prior to using the location APIs. This example checks for user consent in the OnNavigatedTo(NavigationEventArgs) method of the MainPage class, which is called whenever the app is launched. The code first checks the ApplicationSettings dictionary for the “LocationConsent” key. If the key is found, it means the user has already opted in or out of location, so the method returns immediately. If the key is not found, then a MessageBox is shown asking for user consent. The result of the MessageBox operation is checked and a Boolean value indicating the user consent status is stored in the “LocationConsent” key in ApplicationSettings. This key will be checked before the app attempts to access the user’s location.

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        if (IsolatedStorageSettings.ApplicationSettings.Contains("LocationConsent"))
        {
            // User has opted in or out of Location
            return;
        }
        else
        {
            MessageBoxResult result = 
                MessageBox.Show("This app accesses your phone's location. Is that ok?", 
                "Location",
                MessageBoxButton.OKCancel);
    
            if (result == MessageBoxResult.OK)
            {
                IsolatedStorageSettings.ApplicationSettings["LocationConsent"] = true;
            }else
            {
                IsolatedStorageSettings.ApplicationSettings["LocationConsent"] = false;
            }
    
            IsolatedStorageSettings.ApplicationSettings.Save();
        }
    }
    
  8. Paste the button click handler into MainPage.xaml.cs. This handler will toggle tracking on and off, but first it checks the “LocationConsent” value in the ApplicationSettings dictionary. In the case where the app was not previously tracking location, the Geolocator object is initialized. Then, accuracy and movement threshold are set. The app will be updated only with new location information when the phone moves more than the movement threshold from the previous location. Next, event handlers for the StatusChanged and PositionChanged events are registered. Finally, the tracking variable is set to true and the button text is updated.

    If the app was previously tracking location, the event handler should toggle off tracking. To do this it removes the event handlers for the StatusChanged and PositionChanged events and sets the Geolocator object to null. Finally, the tracking variable and button text are updated.

    private void TrackLocation_Click(object sender, RoutedEventArgs e)
    {
        if ((bool)IsolatedStorageSettings.ApplicationSettings["LocationConsent"] != true)
        {
            // The user has opted out of Location.
            return;
        }
    
        if (!tracking)
        {
            geolocator = new Geolocator();
            geolocator.DesiredAccuracy = PositionAccuracy.High;
            geolocator.MovementThreshold = 100; // The units are meters.
    
            geolocator.StatusChanged += geolocator_StatusChanged;
            geolocator.PositionChanged += geolocator_PositionChanged;
    
            tracking = true;
            TrackLocationButton.Content = "stop tracking";
        }
        else
        {
            geolocator.PositionChanged -= geolocator_PositionChanged;
            geolocator.StatusChanged -= geolocator_StatusChanged;
            geolocator = null;
    
            tracking = false;
            TrackLocationButton.Content = "track location";
            StatusTextBlock.Text = "stopped";
        }
    }
    
  9. Paste the event handler for the StatusChanged event into MainPage.xaml.cs. This event is raised whenever the status of the location service changes. You can use this method to provide feedback to the user. Because this event handler is not called on the UI thread, you must use BeginInvoke(Action) to run any code that modifies the UI.

    void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
    {
        string status = "";
    
        switch (args.Status)
        {
            case PositionStatus.Disabled:
                // the application does not have the right capability or the location master switch is off
                status = "location is disabled in phone settings";
                break;
            case PositionStatus.Initializing:
                // the geolocator started the tracking operation
                status = "initializing";
                break;
            case PositionStatus.NoData:
                // the location service was not able to acquire the location
                status = "no data";
                break;
            case PositionStatus.Ready:
                // the location service is generating geopositions as specified by the tracking parameters
                status = "ready";
                break;
            case PositionStatus.NotAvailable:
                status = "not available";
                // not used in WindowsPhone, Windows desktop uses this value to signal that there is no hardware capable to acquire location information
                break;
            case PositionStatus.NotInitialized:
                // the initial state of the geolocator, once the tracking operation is stopped by the user the geolocator moves back to this state
    
                break;
        }
    
        Dispatcher.BeginInvoke(() =>
        {
            StatusTextBlock.Text = status;
        });
    }
    
  10. Paste the event handler for the PositionChanged event into MainPage.xaml.cs. This event is raised whenever the phone has moved a distance greater that the movement threshold from the previous location. Again, this event handler is not called on the UI thread, so you must use BeginInvoke(Action) to run any code that modifies the UI.

    void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
    {
        Dispatcher.BeginInvoke(() =>
        {
            LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00");
            LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00");
        });
    }