geofencing in windows phone 8.1

Windows Phone 8.1 brings the concept of Geofencing to our beloved Windows Phone platform. Geofencing allows us to trigger an action whenever a user is at a predefined set of coordinates. Windows Phone 8.1 registers geofences with the OS so our app doesn’t need to run for triggers to fire. For this post we’ll trigger a welcome message whenever someone is at building 9 of the Microsoft Redmond campus.

The app

Create a new Windows Phone 8.1 app. Add the Location capability in the Package.appxmanifest. We obviously need location capabilities for this Glimlach

Let’s dive into code. This app will only have a blank MainPage and a message dialog that pops up when we’re near building 9.

First thing we need is a reference to the current GeofenceMonitor.

<div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:f96ef22c-aa05-493b-a728-ab2b65b240e7" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#2b91af">GeofenceMonitor</span><span style="background:#ffffff;color:#000000"> _monitor = </span><span style="background:#ffffff;color:#2b91af">GeofenceMonitor</span><span style="background:#ffffff;color:#000000">.Current;</span></li> </ol> </div> </div> </div>    <p>Setting the Geofence location and hooking up the event happens in the constructor</p>  <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:7c3d6279-9a46-432e-8998-a52bacf438e0" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 500px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">public</span><span style="background:#ffffff;color:#000000"> MainPage()</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li>    <span style="background:#ffffff;color:#000000">InitializeComponent();</span></li> <li style="background: #f3f3f3">&nbsp;</li> <li>    <span style="background:#ffffff;color:#000000">_monitor.GeofenceStateChanged += MonitorOnGeofenceStateChanged;</span></li> <li style="background: #f3f3f3">&nbsp;</li> <li>    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#008000">//Microsoft Redmond building 9</span></li> <li style="background: #f3f3f3">    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">BasicGeoposition</span><span style="background:#ffffff;color:#000000"> pos = </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">BasicGeoposition</span><span style="background:#ffffff;color:#000000"> { Latitude = 47.6397, Longitude = -122.1289 };</span></li> <li>&nbsp;</li> <li style="background: #f3f3f3">    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">Geofence</span><span style="background:#ffffff;color:#000000"> fence = </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">Geofence</span><span style="background:#ffffff;color:#000000">(</span><span style="background:#ffffff;color:#a31515">&quot;building9&quot;</span><span style="background:#ffffff;color:#000000">, </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">Geocircle</span><span style="background:#ffffff;color:#000000">(pos, 100));</span></li> <li>&nbsp;</li> <li style="background: #f3f3f3">    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">try</span></li> <li>    <span style="background:#ffffff;color:#000000">{</span></li> <li style="background: #f3f3f3">        <span style="background:#ffffff;color:#000000">_monitor.Geofences.Add(fence);</span></li> <li>    <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3">    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">catch</span><span style="background:#ffffff;color:#000000"> (</span><span style="background:#ffffff;color:#2b91af">Exception</span><span style="background:#ffffff;color:#000000">)</span></li> <li>    <span style="background:#ffffff;color:#000000">{</span></li> <li style="background: #f3f3f3">        <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#008000">//geofence already added to system</span></li> <li>    <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div>  <p>First we hook up the GeofenceStateChanged event, we’ll look at the eventhandler in a minute. Then we create a BasicGeoPosition which holds the coordinates for, in our case, building 9 of the Microsoft campus in Redmond. Then we create a Geofence. The Geofence constructor takes two parameters, a string that functions as ID so it should be unique, and an IGeoShape. Other overloads for Geofence allow us to specify if we want to trigger the event whenever we enter or leave the geofence area.</p>  <p>For the ID we use a string, for the IGeoShape we use a GeoCircle. Other build-in possibilities are</p>  <ul>   <li>Geoboundingbox </li>    <li>Geocircle </li>    <li>Geopath </li>    <li>Geopoint </li> </ul>  <p>The Geocircle takes two parameters, the position and the radius (in meters). We’ve already defined a position as BasicGeoposition, which is exactly the type expected by the Geocircle, and we define a radius of 100 meters. Finally we try to add the Geofence to the geofences registered in the OS. If a Geofence with the same ID already exists it will throw an exception stating that the object already exists.</p>  <p><img src="http://i60.tinypic.com/rrpfns.jpg" /></p>  <p>Let’s have a look at the event handler</p>  <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c530d420-1f8c-4f9c-8700-fc8599263c39" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 500px; overflow: auto"> <ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"> <li><span style="background:#ffffff;color:#0000ff">private</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#0000ff">void</span><span style="background:#ffffff;color:#000000"> MonitorOnGeofenceStateChanged(</span><span style="background:#ffffff;color:#2b91af">GeofenceMonitor</span><span style="background:#ffffff;color:#000000"> sender, </span><span style="background:#ffffff;color:#0000ff">object</span><span style="background:#ffffff;color:#000000"> args)</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">{</span></li> <li>    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">var</span><span style="background:#ffffff;color:#000000"> fences = sender.ReadReports();</span></li> <li style="background: #f3f3f3">&nbsp;</li> <li>    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">foreach</span><span style="background:#ffffff;color:#000000"> (</span><span style="background:#ffffff;color:#0000ff">var</span><span style="background:#ffffff;color:#000000"> report </span><span style="background:#ffffff;color:#0000ff">in</span><span style="background:#ffffff;color:#000000"> fences)</span></li> <li style="background: #f3f3f3">    <span style="background:#ffffff;color:#000000">{</span></li> <li>        <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">if</span><span style="background:#ffffff;color:#000000"> (report.Geofence.Id != </span><span style="background:#ffffff;color:#a31515">&quot;building9&quot;</span><span style="background:#ffffff;color:#000000">)</span></li> <li style="background: #f3f3f3">            <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">continue</span><span style="background:#ffffff;color:#000000">;</span></li> <li>&nbsp;</li> <li style="background: #f3f3f3">        <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">switch</span><span style="background:#ffffff;color:#000000"> (report.NewState)</span></li> <li>        <span style="background:#ffffff;color:#000000">{</span></li> <li style="background: #f3f3f3">            <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">case</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">GeofenceState</span><span style="background:#ffffff;color:#000000">.Entered:</span></li> <li>                <span style="background:#ffffff;color:#000000">Dispatcher.RunAsync(</span><span style="background:#ffffff;color:#2b91af">CoreDispatcherPriority</span><span style="background:#ffffff;color:#000000">.Normal, </span><span style="background:#ffffff;color:#0000ff">async</span><span style="background:#ffffff;color:#000000"> () =&gt;</span></li> <li style="background: #f3f3f3">                <span style="background:#ffffff;color:#000000">{</span></li> <li>                    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">MessageDialog</span><span style="background:#ffffff;color:#000000"> dialog = </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">MessageDialog</span><span style="background:#ffffff;color:#000000">(</span><span style="background:#ffffff;color:#a31515">&quot;Welcome to building 9&quot;</span><span style="background:#ffffff;color:#000000">);</span></li> <li style="background: #f3f3f3">&nbsp;</li> <li>                    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">await</span><span style="background:#ffffff;color:#000000"> dialog.ShowAsync();</span></li> <li style="background: #f3f3f3">                <span style="background:#ffffff;color:#000000">});</span></li> <li>                <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">break</span><span style="background:#ffffff;color:#000000">;</span></li> <li style="background: #f3f3f3">            <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">case</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">GeofenceState</span><span style="background:#ffffff;color:#000000">.Exited:</span></li> <li>                <span style="background:#ffffff;color:#000000">Dispatcher.RunAsync(</span><span style="background:#ffffff;color:#2b91af">CoreDispatcherPriority</span><span style="background:#ffffff;color:#000000">.Normal, </span><span style="background:#ffffff;color:#0000ff">async</span><span style="background:#ffffff;color:#000000"> () =&gt;</span></li> <li style="background: #f3f3f3">                <span style="background:#ffffff;color:#000000">{</span></li> <li>                    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#2b91af">MessageDialog</span><span style="background:#ffffff;color:#000000"> dialog = </span><span style="background:#ffffff;color:#0000ff">new</span><span style="background:#ffffff;color:#000000"> </span><span style="background:#ffffff;color:#2b91af">MessageDialog</span><span style="background:#ffffff;color:#000000">(</span><span style="background:#ffffff;color:#a31515">&quot;Leaving building 9&quot;</span><span style="background:#ffffff;color:#000000">);</span></li> <li style="background: #f3f3f3">&nbsp;</li> <li>                    <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">await</span><span style="background:#ffffff;color:#000000"> dialog.ShowAsync();</span></li> <li style="background: #f3f3f3">                <span style="background:#ffffff;color:#000000">});</span></li> <li>                <span style="background:#ffffff;color:#000000"></span><span style="background:#ffffff;color:#0000ff">break</span><span style="background:#ffffff;color:#000000">;</span></li> <li style="background: #f3f3f3">        <span style="background:#ffffff;color:#000000">}</span></li> <li>    <span style="background:#ffffff;color:#000000">}</span></li> <li style="background: #f3f3f3"><span style="background:#ffffff;color:#000000">}</span></li> </ol> </div> </div> </div>  <p>Before we can show a message we’ll need to know what geofence triggered the event. We do that by calling ReadReports on the GeofenceMonitor. This method will return a ReadOnlyList containing GeofenceStateChangedReports. Iterating over those reports we can check the ID of the geofence and take action when the expected geofence is triggered. In this case we want to show a welcome message when someone arrives and a leaving message when someone leaves. Let’s try it out!</p>  <p>Launch the app in the emulator (unless you’re physically at building 9, then you can use a WP8.1 device <img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-bottom-style: none; border-right-style: none; border-left-style: none" alt="Glimlach" src="http://www.spikie.be/blog/images/wlEmoticon-smile_31.png" />), open the emulator tools and set the location to building 9. You’ll have to wait some seconds before the message pops up, this is to prevent triggers being fired when just passing through a geofence location. You can manipulate this delay by using an overload of the Geofence constructor and setting the DwellTime parameter (TimeSpan).</p>  <p><a href="http://i59.tinypic.com/r88mkg.jpg" target="_blank"><img src="http://i59.tinypic.com/r88mkg.jpg" width="586" height="379" /></a></p>  <p>Clear your location and set it somewhere away from building 9, wait a few seconds and watch the leaving message.</p>  <p><a href="http://i62.tinypic.com/icijw1.jpg" target="_blank"><img src="http://i62.tinypic.com/icijw1.jpg" width="590" height="315" /></a></p>  <h2>Conclusion</h2>  <p>Geofencing is a pretty cool way to interact with users based on their location. It’s a great addition to the platform and personally I can’t wait to see what great ideas devs will come up with to use this functionality.</p>  <p>In this post I did a quick, basic lap around geofencing. Geofences can also trigger a backgroundtask, provided the app is set as lockscreen app, so the app doesn’t need to run all the time for geofencing to do its stuff.</p>  <p>As usual, the code can be found on my <a href="http://1drv.ms/1pYq88z" target="_blank">OneDrive</a></p>

This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.

Leave a Comment