Set up a geofence (XAML)

Learn how to set up a Geofence in your app. This topic uses code examples, some of which are based on the geolocation sample, to demonstrate key points. For more info, download and run the sample.

Roadmap: How does this topic relate to others? See:

Step 1: Verify that location is enabled

Before your app can access location, Location must be enabled on the device. In the Settings app, check that the following location privacy settings are turned on:

  • Location for this device... is turned on (not applicable in Windows 10 Mobile)
  • The location services setting, Location, is turned on
  • Under Choose apps that can use your location, your app is set to on

Step 2: Enable the location capability

Double click on package.appxmanifest in Solution Explorer and select the Capabilities tab. Then check Location in the Capabilities list. This adds the Location device capability to the package manifest file.

  <Capabilities>
    <!-- DeviceCapability elements must follow Capability elements (if present) -->
    <DeviceCapability Name="location"/>
  </Capabilities>

Step 3: Request access to the user's location

Request access to the user's location using the RequestAccessAsync method.

Important  Starting in Windows 10, call the RequestAccessAsync before accessing the user’s location. At that time, your app must be in the foreground and RequestAccessAsync must be called from the UI thread. Until the user grants your app permission to their location, your app can't access location data.

 

using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();

The RequestAccessAsync method prompts the user for permission to access their location. The user is only prompted once (per app). After the first time they grant or deny permission, this method no longer prompts for permission. To help the user change location permissions after they've been prompted, we recommend providing a link to the location settings as demonstrated later in this topic.

Step 4: Register for changes in geofence state and location permissions

In this example, a switch statement is used with accessStatus (from the previous example) to act only when access to location is allowed. If allowed, the code accesses the current geofences, registers for geofence state changes, and registers for changes in location permissions.

Tip  When using a geofence, use the GeofenceMonitor's StatusChanged event to monitor changes in location permissions instead of the StatusChanged event from the Geolocator class. A GeofenceMonitorStatus of Disabled is equivalent to a disabled PositionStatus - both indicate that the app does not have permission to access location.

 

switch (accessStatus)
{
    case GeolocationAccessStatus.Allowed:
        geofences = GeofenceMonitor.Current.Geofences;

        FillRegisteredGeofenceListBoxWithExistingGeofences();
        FillEventListBoxWithExistingEvents();

        // register for state change events
        GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
        GeofenceMonitor.Current.StatusChanged += OnGeofenceStatusChanged;
        break;

    case GeolocationAccessStatus.Denied:
        _rootPage.NotifyUser("Access denied.", NotifyType.ErrorMessage);
        break;

    case GeolocationAccessStatus.Unspecified:
        _rootPage.NotifyUser("Unspecified error.", NotifyType.ErrorMessage);
        break;
}

Then, when navigating away from your foreground app, unregister the event listeners.

protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    GeofenceMonitor.Current.GeofenceStateChanged -= OnGeofenceStateChanged;
    GeofenceMonitor.Current.StatusChanged -= OnGeofenceStatusChanged;

    base.OnNavigatingFrom(e);
}

Step 5: Create the geofence

Now you are ready to define and set up a Geofence object. There are several different constructor overloads to choose from, depending on your needs. In the most basic geofence constructor, specify only the Id and the Geoshape as shown here.

// Set fence ID
string fenceId = "fence1";

// Define fence location and radius
BasicGeoposition position;
position.Latitude = 47.6510;
position.Longitude = -122.3473;
position.Altitude = 0.0;
double radius = 10; // in meters

// Set circular region for geofence
Geocircle geocircle = new Geocircle(position, radius);

// Create geofence
Geofence geofence = new Geofence(fenceId, geocircle);

You can fine-tune your geofence further by using one of the other constructors. In the next example, the geofence constructor specifies these additional parameters:

  • The MonitoredStates, which indicate what geofence events you want to receive notifications for - entering the defined region, leaving the defined region, or removal of the geofence.
  • A SingleUse flag, which will remove the geofence once all the states the geofence is being monitored for have been met.
  • A DwellTime, which indicates how long the user must be in or out of the defined area before the enter/exit events are triggered.
  • The StartTime, which indicates when to start monitoring the geofence.
  • The Duration to monitor the geofence for.
// Set fence ID
string fenceId = "fence2";

// Define fence location and radius
BasicGeoposition position;
position.Latitude = 47.6510;
position.Longitude = -122.3473;
position.Altitude = 0.0;
double radius = 10; // in meters

// Set circular region for geofence
Geocircle geocircle = new Geocircle(position, radius);

// Remove geofence after the first trigger
bool singleUse = true;

// Set monitored states
MonitoredGeofenceStates monitoredStates = 
                MonitoredGeofenceStates.Entered | 
                MonitoredGeofenceStates.Exited | 
                MonitoredGeofenceStates.Removed;

// Set how long you need to be in geofence for enter event to fire
TimeSpan dwellTime = TimeSpan.FromMinutes(5);

// Set how long the geofence should be active
TimeSpan duration = TimeSpan.FromDays(1);

// Set up the start time of the geofence
DateTimeOffset startTime = DateTime.Now;

// Create geofence
Geofence geofence = new Geofence(fenceId, geocircle, monitoredStates, singleUse, dwellTime, startTime, duration);

Step 6: Handle changes in location permissions

The GeofenceMonitor object triggers the StatusChanged event to indicate that the user's location settings changed. That event passes the corresponding status via the argument's sender.Status property (of type GeofenceMonitorStatus). Note that this method is not called from the UI thread and the Dispatcher object invokes the UI changes.

using Windows.UI.Core;
...
public async void OnGeofenceStatusChanged(GeofenceMonitor sender, object e)
{
   await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
   {
    // Show the location setting message only if status is disabled.
    LocationDisabledMessage.Visibility = Visibility.Collapsed;

    switch (sender.Status)
    {
     case GeofenceMonitorStatus.Ready:
      _rootPage.NotifyUser("The monitor is ready and active.", NotifyType.StatusMessage);
      break;

     case GeofenceMonitorStatus.Initializing:
      _rootPage.NotifyUser("The monitor is in the process of initializing.", NotifyType.StatusMessage);
      break;

     case GeofenceMonitorStatus.NoData:
      _rootPage.NotifyUser("There is no data on the status of the monitor.", NotifyType.ErrorMessage);
      break;

     case GeofenceMonitorStatus.Disabled:
      _rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);

      // Show message to the user to go to location settings
      LocationDisabledMessage.Visibility = Visibility.Visible;
      break;

     case GeofenceMonitorStatus.NotInitialized:
      _rootPage.NotifyUser("The geofence monitor has not been initialized.", NotifyType.StatusMessage);
      break;

     case GeofenceMonitorStatus.NotAvailable:
      _rootPage.NotifyUser("The geofence monitor is not available.", NotifyType.ErrorMessage);
      break;

     default:
      ScenarioOutput_Status.Text = "Unknown";
      _rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
      break;
    }
   });
}

Step 7: Help the user change location settings

If the location settings don't allow your app to access the user's location, we recommend providing a convenient link to the location privacy settings in the Settings app. In this example, a Hyperlink control is used navigate to the ms-settings:privacy-location URI.

<!--Set Visibility to Visible when access to location is denied -->  
<TextBlock x:Name="LocationDisabledMessage" FontStyle="Italic" 
                 Visibility="Collapsed" Margin="0,15,0,0" TextWrapping="Wrap" >
          <Run Text="This app is not able to access Location. Go to " />
              <Hyperlink NavigateUri="ms-settings:privacy-location">
                  <Run Text="Settings" />
              </Hyperlink>
          <Run Text=" to check the location privacy settings."/>
</TextBlock>

Alternatively, your app can call the LaunchUriAsync method to launch the Settings app from code. For more info, see How to launch the Settings app.

using Windows.System;
...
bool result = await Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));

Step 8: Handle geofence state changes

Once your geofences have been created, you will have to add the logic to handle what happens when a geofence event occurs.

For more info, see:

  1. Handle geofence notifications in the foreground
  2. Listen for geofence events in the background
  3. Handle geofence notifications from a background task

Windows 10 geolocation sample

Windows 8.1 geolocation sample

Roadmap for apps using C# and Visual Basic

Roadmap for apps using C++

Designing UX for apps

Guidelines for geofencing

Geoshape

Geofence

Geolocator