6
votes

Issue

I'm trying to trigger a BackgroundTask when a Geofence Event (Enter / Exit) occurs in WP8.1 (WinRT). I've written a sample application to try to get it working, but can't seem to be able to do so.

So far, these are the steps I've taken to try to get Geofences working in the background:

  1. Check for Location Capabilities
  2. Create + Register a Geofence
  3. Create + Register a BackgroundTask that listens for LocationTrigger(LocationTriggerType.Geofence);
  4. In my background task, trigger a simple popup notification

Things I have done to Troubleshoot

I have enabled in my app.manifest:

  • Toast Capable => Yes
  • Capabilities: Location, Internet(Client & Server)
  • Declarations: BackgroundTasks (Location). EntryPoint = BackgroundTask.GeofenceBackgroundTask

My background task is located in a separate project, titled BackgroundTask. It is a WindowsRT Component and contains one class GeofenceBackgroundTask.

Project Layout

Sample Project

The code for the project can be found at this [link](https://github.com/kiangtengl/GeofenceSample):

How To Test

  1. Run the code in the emulator

  2. Set Location to to: Latitude = 01.3369, Longitude = 103.7364

enter image description here

  1. Click the Register Geofence + BackgroundTasks button

  2. Exit the app (press the home button)

  3. Change the current location to anywhere 100m away from the location you set previously. A notification should pop out.

Project Code:

Check for Location Capabilities

    public static async Task GetLocationCapabilities()
    {
        try
        {
            var geolocator = new Geolocator();
            await geolocator.GetGeopositionAsync();
            var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
            Debug.WriteLine("background access status" + backgroundAccessStatus);
        }
        catch (UnauthorizedAccessException e)
        {
            Debug.WriteLine(e);
        }
        catch (TaskCanceledException e)
        {
            Debug.WriteLine(e);
        }
    }

Create Geofence

    public static void CreateGeofence(BasicGeoposition position, double radius, string id = "default")
    {
        // The Geofence is a circular area centered at (latitude, longitude) point, with the
        // radius in meter.
        var geocircle = new Geocircle(position, radius);

        // Sets the events that we want to handle: in this case, the entrace and the exit
        // from an area of intereset.
        var mask = MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited;

        // Specifies for how much time the user must have entered/exited the area before 
        // receiving the notification.
        var dwellTime = TimeSpan.FromSeconds(1);

        // Creates the Geofence and adds it to the GeofenceMonitor.
        var geofence = new Geofence(id, geocircle, mask, false, dwellTime);

        try
        {
            GeofenceMonitor.Current.Geofences.Add(geofence);
        }
        catch (Exception e)
        {
            Debug.WriteLine(e);
            // geofence already added to system
        }

    }

Register Background Task

    public static async Task RegisterBackgroundTask()
    {
        try
        { 
        // Create a new background task builder
        var geofenceTaskBuilder = new BackgroundTaskBuilder()
        {
            Name = GeofenceBackgroundTaskName,
            TaskEntryPoint = "BackgroundTask.GeofenceBackgroundTask"
        };

        // Create a new location trigger
        var trigger = new LocationTrigger(LocationTriggerType.Geofence);

        // Associate the location trigger with the background task builder
        geofenceTaskBuilder.SetTrigger(trigger);

        var geofenceTask = geofenceTaskBuilder.Register();

        // Associate an event handler with the new background task
        geofenceTask.Completed += (sender, e) =>
        {
            try
            {
                e.CheckResult();
            }
            catch(Exception error)
            {
                Debug.WriteLine(error);
            }
        };
        }
        catch(Exception e)
        {
            // Background task probably exists

            Debug.WriteLine(e);
        }
    }

BackgroundTask Code to Trigger Toast

namespace BackgroundTask
{
    public sealed class GeofenceBackgroundTask : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            var toastTemplate = ToastTemplateType.ToastText02;
            var toastXML = ToastNotificationManager.GetTemplateContent(toastTemplate);
            var textElements = toastXML.GetElementsByTagName("text");
            textElements[0].AppendChild(toastXML.CreateTextNode("You have left!"));

            var toast = new ToastNotification(toastXML);

            ToastNotificationManager.CreateToastNotifier().Show(toast);
        }
    }
}
2
Could you please upload the sample project again? it's unavailable :(SuperJMN

2 Answers

3
votes

I've discovered that the above code sample, as well as the above code works. The problem that I was facing was that Windows Phone 8.1 does not automatically trigger a Geofence event. You have to wait a certain amount of time <5 mins before the BackgroundTask is triggered.

This applies to Geofencing in the foreground as well.

0
votes

I'm busy with the same stuff, and I also noticed this behaviour, but for me its 2 mins. Unfortunately it always triggers after 2 min, even, if there was no change in location and still inside the fence..