PageRenderTime 70ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/geolocation/cs/geolocationcs/scenario4_foregroundgeofence.xaml.cs

https://gitlab.com/Rockyspade/Windows-universal-samples
C# | 340 lines | 228 code | 49 blank | 63 comment | 20 complexity | 6388fc00ecd9692b625369d641ded900 MD5 | raw file
  1. //*********************************************************
  2. //
  3. // Copyright (c) Microsoft. All rights reserved.
  4. // This code is licensed under the MIT License (MIT).
  5. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  6. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  7. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  8. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  9. //
  10. //*********************************************************
  11. using SDKTemplate;
  12. using System;
  13. using System.Threading;
  14. using System.Collections.Generic;
  15. using Windows.Devices.Geolocation;
  16. using Windows.Devices.Geolocation.Geofencing;
  17. using Windows.UI.Core;
  18. using Windows.UI.Xaml;
  19. using Windows.UI.Xaml.Controls;
  20. using Windows.UI.Xaml.Navigation;
  21. using Windows.Globalization.DateTimeFormatting;
  22. using Windows.Globalization;
  23. using Windows.Globalization.NumberFormatting;
  24. using System.Collections.ObjectModel;
  25. namespace GeolocationCS
  26. {
  27. public sealed partial class Scenario4 : Page
  28. {
  29. private bool nameSet = false;
  30. private bool latitudeSet = false;
  31. private bool longitudeSet = false;
  32. private bool radiusSet = false;
  33. private int secondsPerMinute = 60;
  34. private int secondsPerHour = 60 * 60;
  35. private int secondsPerDay = 24 * 60 * 60;
  36. private int oneHundredNanosecondsPerSecond = 10000000;
  37. private int defaultDwellTimeSeconds = 10;
  38. private const int maxEventDescriptors = 42; // Value determined by how many max length event descriptors (91 chars)
  39. // stored as a JSON string can fit in 8K (max allowed for local settings)
  40. private CancellationTokenSource _cts = null;
  41. private IList<Geofence> geofences = new List<Geofence>();
  42. private ObservableCollection<GeofenceItem> geofenceCollection = null;
  43. private ObservableCollection<string> eventCollection = null;
  44. private DateTimeFormatter formatterShortDateLongTime;
  45. private DateTimeFormatter formatterLongTime;
  46. private Calendar calendar;
  47. private DecimalFormatter decimalFormatter;
  48. private CoreWindow coreWindow;
  49. // A pointer to the main page.
  50. private MainPage _rootPage = MainPage.Current;
  51. public Scenario4()
  52. {
  53. this.InitializeComponent();
  54. try
  55. {
  56. formatterShortDateLongTime = new DateTimeFormatter("{month.integer}/{day.integer}/{year.full} {hour.integer}:{minute.integer(2)}:{second.integer(2)}", new[] { "en-US" }, "US", Windows.Globalization.CalendarIdentifiers.Gregorian, Windows.Globalization.ClockIdentifiers.TwentyFourHour);
  57. formatterLongTime = new DateTimeFormatter("{hour.integer}:{minute.integer(2)}:{second.integer(2)}", new[] { "en-US" }, "US", Windows.Globalization.CalendarIdentifiers.Gregorian, Windows.Globalization.ClockIdentifiers.TwentyFourHour);
  58. calendar = new Calendar();
  59. decimalFormatter = new DecimalFormatter();
  60. geofenceCollection = new ObservableCollection<GeofenceItem>();
  61. eventCollection = new ObservableCollection<string>();
  62. // Geofencing setup
  63. InitializeGeolocation();
  64. // using data binding to the root page collection of GeofenceItems
  65. RegisteredGeofenceListBox.DataContext = geofenceCollection;
  66. // using data binding to the root page collection of GeofenceItems associated with events
  67. GeofenceEventsListBox.DataContext = eventCollection;
  68. coreWindow = CoreWindow.GetForCurrentThread(); // this needs to be set before InitializeComponent sets up event registration for app visibility
  69. coreWindow.VisibilityChanged += OnVisibilityChanged;
  70. }
  71. catch (Exception ex)
  72. {
  73. // GeofenceMonitor failed in adding a geofence
  74. // exceptions could be from out of memory, lat/long out of range,
  75. // too long a name, not a unique name, specifying an activation
  76. // time + duration that is still in the past
  77. _rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
  78. }
  79. }
  80. private async void InitializeGeolocation()
  81. {
  82. // Get permission to use location
  83. var accessStatus = await Geolocator.RequestAccessAsync();
  84. switch (accessStatus)
  85. {
  86. case GeolocationAccessStatus.Allowed:
  87. geofences = GeofenceMonitor.Current.Geofences;
  88. FillRegisteredGeofenceListBoxWithExistingGeofences();
  89. FillEventListBoxWithExistingEvents();
  90. // register for state change events
  91. GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
  92. GeofenceMonitor.Current.StatusChanged += OnGeofenceStatusChanged;
  93. break;
  94. case GeolocationAccessStatus.Denied:
  95. _rootPage.NotifyUser("Access denied.", NotifyType.ErrorMessage);
  96. break;
  97. case GeolocationAccessStatus.Unspecified:
  98. _rootPage.NotifyUser("Unspecified error.", NotifyType.ErrorMessage);
  99. break;
  100. }
  101. }
  102. /// <summary>
  103. /// Invoked when this page is about to be displayed in a Frame.
  104. /// </summary>
  105. /// <param name="e">Event data that describes how this page was reached. The Parameter
  106. /// property is typically used to configure the page.</param>
  107. protected override void OnNavigatedTo(NavigationEventArgs e)
  108. {
  109. }
  110. /// <summary>
  111. /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
  112. /// </summary>
  113. /// <param name="e">
  114. /// Event data that can be examined by overriding code. The event data is representative
  115. /// of the navigation that will unload the current Page unless canceled. The
  116. /// navigation can potentially be canceled by setting e.Cancel to true.
  117. /// </param>
  118. protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
  119. {
  120. if (_cts != null)
  121. {
  122. _cts.Cancel();
  123. _cts = null;
  124. }
  125. GeofenceMonitor.Current.GeofenceStateChanged -= OnGeofenceStateChanged;
  126. GeofenceMonitor.Current.StatusChanged -= OnGeofenceStatusChanged;
  127. // save off the contents of the event collection
  128. SaveExistingEvents();
  129. base.OnNavigatingFrom(e);
  130. }
  131. private void OnVisibilityChanged(CoreWindow sender, VisibilityChangedEventArgs args)
  132. {
  133. // NOTE: After the app is no longer visible on the screen and before the app is suspended
  134. // you might want your app to use toast notification for any geofence activity.
  135. // By registering for VisibiltyChanged the app is notified when the app is no longer visible in the foreground.
  136. if (args.Visible)
  137. {
  138. // register for foreground events
  139. GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
  140. GeofenceMonitor.Current.StatusChanged += OnGeofenceStatusChanged;
  141. }
  142. else
  143. {
  144. // unregister foreground events (let background capture events)
  145. GeofenceMonitor.Current.GeofenceStateChanged -= OnGeofenceStateChanged;
  146. GeofenceMonitor.Current.StatusChanged -= OnGeofenceStatusChanged;
  147. }
  148. }
  149. public async void OnGeofenceStatusChanged(GeofenceMonitor sender, object e)
  150. {
  151. var status = sender.Status;
  152. string eventDescription = GetTimeStampedMessage("Geofence Status Changed");
  153. eventDescription += " (" + status.ToString() + ")";
  154. await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
  155. {
  156. AddEventDescription(eventDescription);
  157. });
  158. }
  159. public async void OnGeofenceStateChanged(GeofenceMonitor sender, object e)
  160. {
  161. var reports = sender.ReadReports();
  162. await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
  163. {
  164. foreach (GeofenceStateChangeReport report in reports)
  165. {
  166. GeofenceState state = report.NewState;
  167. Geofence geofence = report.Geofence;
  168. string eventDescription = GetTimeStampedMessage(geofence.Id) +
  169. " (" + state.ToString();
  170. if (state == GeofenceState.Removed)
  171. {
  172. eventDescription += "/" + report.RemovalReason.ToString() + ")";
  173. AddEventDescription(eventDescription);
  174. // remove the geofence from the client side geofences collection
  175. Remove(geofence);
  176. // empty the registered geofence listbox and repopulate
  177. geofenceCollection.Clear();
  178. FillRegisteredGeofenceListBoxWithExistingGeofences();
  179. }
  180. else if (state == GeofenceState.Entered || state == GeofenceState.Exited)
  181. {
  182. // NOTE: You might want to write your app to take particular
  183. // action based on whether the app has internet connectivity.
  184. eventDescription += ")";
  185. AddEventDescription(eventDescription);
  186. }
  187. }
  188. });
  189. }
  190. /// <summary>
  191. /// This method removes the geofence from the client side geofences collection
  192. /// </summary>
  193. /// <param name="geofence"></param>
  194. private void Remove(Geofence geofence)
  195. {
  196. try
  197. {
  198. if (!geofences.Remove(geofence))
  199. {
  200. var strMsg = "Could not find Geofence " + geofence.Id + " in the geofences collection";
  201. _rootPage.NotifyUser(strMsg, NotifyType.StatusMessage);
  202. }
  203. }
  204. catch (Exception ex)
  205. {
  206. _rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
  207. }
  208. }
  209. /// <summary>
  210. /// This is the click handler for the 'Remove Geofence Item' button.
  211. /// </summary>
  212. /// <param name="sender"></param>
  213. /// <param name="e"></param>
  214. private void OnRemoveGeofenceItem(object sender, RoutedEventArgs e)
  215. {
  216. if (null != RegisteredGeofenceListBox.SelectedItem)
  217. {
  218. // get selected item
  219. GeofenceItem itemToRemove = RegisteredGeofenceListBox.SelectedItem as GeofenceItem;
  220. var geofence = itemToRemove.Geofence;
  221. // remove the geofence from the client side geofences collection
  222. Remove(geofence);
  223. // empty the registered geofence listbox and repopulate
  224. geofenceCollection.Clear();
  225. FillRegisteredGeofenceListBoxWithExistingGeofences();
  226. }
  227. }
  228. private Geofence GenerateGeofence()
  229. {
  230. string fenceKey = new string(Id.Text.ToCharArray());
  231. BasicGeoposition position;
  232. position.Latitude = Double.Parse(Latitude.Text);
  233. position.Longitude = Double.Parse(Longitude.Text);
  234. position.Altitude = 0.0;
  235. double radius = Double.Parse(Radius.Text);
  236. // the geofence is a circular region
  237. Geocircle geocircle = new Geocircle(position, radius);
  238. bool singleUse = (bool)SingleUse.IsChecked;
  239. // want to listen for enter geofence, exit geofence and remove geofence events
  240. // you can select a subset of these event states
  241. MonitoredGeofenceStates mask = MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited | MonitoredGeofenceStates.Removed;
  242. TimeSpan dwellTime;
  243. TimeSpan duration;
  244. DateTimeOffset startTime;
  245. try
  246. {
  247. // setting up how long you need to be in geofence for enter event to fire
  248. if (string.Empty != DwellTime.Text)
  249. {
  250. dwellTime = new TimeSpan(ParseTimeSpan(DwellTime.Text, defaultDwellTimeSeconds));
  251. }
  252. else
  253. {
  254. dwellTime = new TimeSpan(ParseTimeSpan("0", defaultDwellTimeSeconds));
  255. }
  256. // setting up how long the geofence should be active
  257. if (string.Empty != Duration.Text)
  258. {
  259. duration = new TimeSpan(ParseTimeSpan(Duration.Text, 0));
  260. }
  261. else
  262. {
  263. duration = new TimeSpan(ParseTimeSpan("0", 0));
  264. }
  265. // setting up the start time of the geofence
  266. if (string.Empty != StartTime.Text)
  267. {
  268. startTime = DateTimeOffset.Parse(StartTime.Text);
  269. }
  270. else
  271. {
  272. // if you don't set start time in C# the start time defaults to 1/1/1601
  273. calendar.SetToNow();
  274. startTime = calendar.GetDateTime();
  275. }
  276. }
  277. catch (ArgumentNullException)
  278. {
  279. }
  280. catch (FormatException)
  281. {
  282. _rootPage.NotifyUser("Entered value is not a valid string representation of a date and time", NotifyType.ErrorMessage);
  283. }
  284. catch (ArgumentException)
  285. {
  286. _rootPage.NotifyUser("The offset is greater than 14 hours or less than -14 hours.", NotifyType.ErrorMessage);
  287. }
  288. return new Geofence(fenceKey, geocircle, mask, singleUse, dwellTime, startTime, duration);
  289. }
  290. }
  291. }