2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Threading.Tasks;
20 using Tizen.Internals.Errors;
21 using System.Runtime.InteropServices;
23 namespace Tizen.Location
25 static internal class Globals
27 internal const string LogTag = "Tizen.Location";
31 /// This class contains the functionality for obtaining the geographical information and setting the boundary condition.
32 /// Notifications on events like service becoming enabled or disabled, new position data being available,
33 /// and others can also be acquired.
35 /// <since_tizen> 3 </since_tizen>
36 public class Locator : IDisposable
38 private int _interval = 1;
39 private int _stayInterval = 120;
40 private int _batchInterval = 0;
41 private int _batchPeriod = 0;
42 private int _requestId = 0;
43 private double _distance = 120.0;
44 private bool _isEnableMock = false;
45 private bool _disposed = false;
46 private bool _isStarted = false;
47 private IntPtr _handle;
48 private LocationType _locationType;
49 private Location _location = null;
50 private Dictionary<IntPtr, Interop.LocatorEvent.LocationUpdatedCallback> _callback_map = new Dictionary<IntPtr, Interop.LocatorEvent.LocationUpdatedCallback>();
52 private Interop.LocatorEvent.ServiceStatechangedCallback _serviceStateChangedCallback;
53 private Interop.LocatorEvent.ZonechangedCallback _zoneChangedCallback;
54 private Interop.LocatorEvent.SettingchangedCallback _settingChangedCallback;
55 private Interop.LocatorEvent.LocationchangedCallback _distanceBasedLocationChangedCallback;
56 private Interop.LocatorEvent.LocationchangedCallback _locationChangedCallback;
57 private Interop.LocatorEvent.LocationBatchCallback _locationBatchCallback;
58 private Interop.LocatorEvent.LocationBatchGetCallback _locationBatchGetCallback;
60 private EventHandler<ZoneChangedEventArgs> _zoneChanged;
61 private EventHandler<ServiceStateChangedEventArgs> _serviceStateChanged;
62 private EventHandler<SettingChangedEventArgs> _settingChanged;
63 private EventHandler<LocationChangedEventArgs> _distanceBasedLocationChanged;
64 private EventHandler<LocationChangedEventArgs> _locationChanged;
67 /// The constructor of the Locator class.
69 /// <since_tizen> 3 </since_tizen>
70 /// <param name="locationType"> The back-end positioning method to be used for LBS.</param>
71 /// <feature>http://tizen.org/feature/location.gps</feature>
72 /// <feature>http://tizen.org/feature/location.wps</feature>
73 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
74 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
75 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
76 public Locator(LocationType locationType)
78 Log.Info(Globals.LogTag, "Locator Constructor");
79 int ret = Interop.Locator.Create((int)locationType, out _handle);
80 if (((LocationError)ret != LocationError.None))
82 Log.Error(Globals.LogTag, "Error creating Location Manager," + (LocationError)ret);
83 throw LocationErrorFactory.ThrowLocationException(ret);
85 _location = new Location();
86 _locationType = locationType;
90 /// The destructor of the Locator class.
92 /// <since_tizen> 3 </since_tizen>
99 /// The time interval between callback updates.
100 /// Should be in the range of 1~120 seconds.
102 /// <since_tizen> 3 </since_tizen>
103 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
108 Log.Info(Globals.LogTag, "Getting the Callback Interval");
113 Log.Info(Globals.LogTag, "Setting the Callback Interval");
114 if (value > 0 && value <= 120)
120 Log.Error(Globals.LogTag, "Error setting Callback Interval");
121 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
127 /// The time interval between the distance-based location callback updates.
128 /// Should be in the range of 1~120 seconds.
130 /// <since_tizen> 3 </since_tizen>
131 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
132 public int StayInterval
136 Log.Info(Globals.LogTag, "Getting the StayInterval");
137 return _stayInterval;
141 Log.Info(Globals.LogTag, "Setting the StayInterval");
142 if (value > 0 && value <= 120)
144 _stayInterval = value;
148 Log.Error(Globals.LogTag, "Error Setting the StayInterval");
149 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
155 /// The time interval between the position collection in batch mode.
156 /// Should be in the range of 1~255 seconds.
158 /// <since_tizen> 3 </since_tizen>
159 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
160 public int BatchInterval
164 Log.Info(Globals.LogTag, "Getting the Batch Interval");
165 return _batchInterval;
169 Log.Info(Globals.LogTag, "Setting the Batch Interval");
170 if (value > 0 && value <= 255)
172 _batchInterval = value;
176 Log.Error(Globals.LogTag, "Error setting Callback Interval");
177 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
183 /// The time interval between batch callback updates. The BatchPeriod should be greater than or equal to the BatchInterval. If the BatchPeriod is zero or smaller than the BatchInterval, then the batch mode will not work. In addition, sometimes the period may not work as you intended, the maximum permissible value for the batch period is device specific.
184 /// Should be in the range of 0~60000 seconds.
186 /// <since_tizen> 3 </since_tizen>
187 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
188 public int BatchPeriod
192 Log.Info(Globals.LogTag, "Getting the Batch Period");
197 Log.Info(Globals.LogTag, "Setting the Batch Period");
198 if (value >= 0 && value <= 60000)
200 _batchPeriod = value;
204 Log.Error(Globals.LogTag, "Error setting Batch Period");
205 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
211 /// The distance between callback updates.
212 /// Should be in the range of 1-120 meters.
214 /// <since_tizen> 3 </since_tizen>
215 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
216 public double Distance
220 Log.Info(Globals.LogTag, "Getting the Distance Interval");
225 Log.Info(Globals.LogTag, "Setting the Distance Interval");
226 if (value > 0 && value <= 120)
232 Log.Error(Globals.LogTag, "Error Setting the Distance");
233 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
239 /// Gets the location object.
241 /// <since_tizen> 3 </since_tizen>
242 public Location Location
246 Log.Info(Globals.LogTag, "Getting location details");
252 /// Gets the type used to obtain the location data.
254 /// <since_tizen> 3 </since_tizen>
255 public LocationType LocationType
259 Log.Info(Globals.LogTag, "Getting LocationType");
260 return _locationType;
265 /// Gets the status whether the mock location is enabled or not.
267 /// <since_tizen> 3 </since_tizen>
268 /// <privilege>http://tizen.org/privilege/location</privilege>
269 /// <exception cref="UnauthroizedAccessException">Thrown when the application has no privilege to use the location.</exception>
270 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
271 public bool EnableMock
275 Log.Info(Globals.LogTag, "Getting getting Mock");
276 _isEnableMock = GetEnableMock();
277 return _isEnableMock;
281 _isEnableMock = value;
286 internal IntPtr GetHandle()
291 private bool GetEnableMock()
294 int ret = Interop.Locator.IsEnabledMock(out status);
295 if (((LocationError)ret != LocationError.None))
297 Log.Error(Globals.LogTag, "Error Get Enable Mock Status," + (LocationError)ret);
298 throw LocationErrorFactory.ThrowLocationException(ret);
303 private void SetEnableMock()
305 int ret = Interop.Locator.EnableMock(_isEnableMock);
306 if (((LocationError)ret != LocationError.None))
308 Log.Error(Globals.LogTag, "Error Set Enable Mock Status," + (LocationError)ret);
309 throw LocationErrorFactory.ThrowLocationException(ret);
314 /// Starts the Location Manager which has been created using the specified method.
316 /// <since_tizen> 3 </since_tizen>
317 /// <privilege>http://tizen.org/privilege/location</privilege>
318 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
319 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
320 /// <exception cref="UnauthroizedAccessException">Thrown when the application has no privilege to use the location.</exception>
321 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
324 Log.Info(Globals.LogTag, "Starting Location Manager");
325 if (_batchPeriod > 0 && _batchPeriod > _batchInterval)
327 int ret = Interop.Locator.StartBatch(_handle);
328 if (((LocationError)ret != LocationError.None))
330 Log.Error(Globals.LogTag, "Error Starting Location Batch mode," + (LocationError)ret);
331 throw LocationErrorFactory.ThrowLocationException(ret);
336 int ret = Interop.Locator.Start(_handle);
337 if (((LocationError)ret != LocationError.None))
339 Log.Error(Globals.LogTag, "Error Starting Location Manager," + (LocationError)ret);
340 throw LocationErrorFactory.ThrowLocationException(ret);
347 /// Stops the Location Manager which has been activated using the specified method.
348 /// Does not destroy the manager.
350 /// <since_tizen> 3 </since_tizen>
351 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
352 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
353 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
356 Log.Info(Globals.LogTag, "Stopping Location Manager");
357 int ret = Interop.Locator.Stop(_handle);
358 if (((LocationError)ret != LocationError.None))
360 Log.Error(Globals.LogTag, "Error stopping Location Manager," + (LocationError)ret);
361 throw LocationErrorFactory.ThrowLocationException(ret);
367 /// Sets a mock location for the given location method.
369 /// <since_tizen> 3 </since_tizen>
370 /// <param name="location"> The location object containing the mock location details.</param>
371 /// <privilege>http://tizen.org/privilege/location</privilege>
372 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
373 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
374 /// <exception cref="UnauthroizedAccessException">Thrown when the application has no privilege to use the location.</exception>
375 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
376 public void SetMockLocation(Location location)
378 Log.Info(Globals.LogTag, "Setting mock location");
379 int ret = Interop.Locator.SetMockLocation(_handle, location.Latitude, location.Longitude, location.Altitude, location.Speed, location.Direction, location.Accuracy);
380 if (((LocationError)ret == LocationError.None))
382 _location.Latitude = location.Latitude;
383 _location.Longitude = location.Longitude;
384 _location.Altitude = location.Altitude;
385 _location.Speed = location.Speed;
386 _location.Direction = location.Direction;
387 _location.Accuracy = location.Accuracy;
391 Log.Error(Globals.LogTag, "Error in setting up location mocking," + (LocationError)ret);
392 throw LocationErrorFactory.ThrowLocationException(ret);
397 /// Clears a mock location for the given location method.
399 /// <since_tizen> 3 </since_tizen>
400 /// <privilege>http://tizen.org/privilege/location</privilege>
401 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
402 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
403 /// <exception cref="UnauthroizedAccessException">Thrown when the application has no privilege to use the location.</exception>
404 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
405 public void ClearMock()
407 Log.Info(Globals.LogTag, "Clear mock location");
408 int ret = Interop.Locator.ClearMock(_handle);
409 if (((LocationError)ret != LocationError.None))
411 Log.Error(Globals.LogTag, "Error in clear up location mocking," + (LocationError)ret);
412 throw LocationErrorFactory.ThrowLocationException(ret);
417 /// Gets the details of the location asynchronously.
419 /// <since_tizen> 3 </since_tizen>
420 /// <param name="timeout"> Timeout to stop requesting a single location after (seconds).</param>
421 /// <returns> A task which contains the current location details.</returns>
422 /// <privilege>http://tizen.org/privilege/location</privilege>
423 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
424 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
425 /// <exception cref="UnauthroizedAccessException">Thrown when the application has no privilege to use the location.</exception>
426 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
427 public Task<Location> GetLocationAsync(int timeout)
429 var task = new TaskCompletionSource<Location>();
430 IntPtr id = IntPtr.Zero;
433 id = (IntPtr)_requestId++;
434 _callback_map[id] = (LocationError error, double latitude, double longitude, double altitude, int timestamp, double speed, double direction, double climb, IntPtr userData) =>
436 if (error != LocationError.None)
438 Log.Error(Globals.LogTag, "Error in getting up location information," + (LocationError)error);
442 Log.Info(Globals.LogTag, "Creating a current location object");
443 _location = new Location(latitude, longitude, altitude, speed, direction, 0.0, timestamp);
444 task.SetResult(_location);
448 _callback_map.Remove(userData);
453 int ret = Interop.LocatorEvent.GetSingleLocation(_handle, timeout, _callback_map[id], id);
454 if (((LocationError)ret != LocationError.None))
456 Log.Error(Globals.LogTag, "Error in setting up location mocking," + (LocationError)ret);
457 throw LocationErrorFactory.ThrowLocationException(ret);
464 /// Gets the details of the location.
466 /// <since_tizen> 3 </since_tizen>
467 /// <returns> Which contains the current location details.</returns>
468 /// <privilege>http://tizen.org/privilege/location</privilege>
469 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
470 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
471 /// <exception cref="UnauthroizedAccessException">Thrown when the application has no privilege to use the location.</exception>
472 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
473 public Location GetLocation()
476 double longitude = 0;
480 double direction = 0;
488 Log.Info(Globals.LogTag, "Get current location information");
489 int ret = Interop.Locator.GetLocation(_handle, out altitude, out latitude, out longitude, out climb, out direction, out speed, out level, out accuracy, out vertical, out timestamp);
490 if (((LocationError)ret != LocationError.None))
492 Log.Error(Globals.LogTag, "Error in get current location information," + (LocationError)ret);
493 throw LocationErrorFactory.ThrowLocationException(ret);
498 Log.Info(Globals.LogTag, "Get last location information");
499 int ret = Interop.Locator.GetLastLocation(_handle, out altitude, out latitude, out longitude, out climb, out direction, out speed, out level, out accuracy, out vertical, out timestamp);
500 if (((LocationError)ret != LocationError.None))
502 Log.Error(Globals.LogTag, "Error in get last location information," + (LocationError)ret);
503 throw LocationErrorFactory.ThrowLocationException(ret);
507 Location location = new Location(latitude, longitude, altitude, speed, direction, accuracy, timestamp);
508 _location = location;
515 /// Adds a bound for a given locator.
517 /// <since_tizen> 3 </since_tizen>
518 /// <param name="locationBoundary">The boundary object to be added to the locator.</param>
519 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
520 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
521 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
522 public void AddBoundary(LocationBoundary locationBoundary)
524 Log.Info(Globals.LogTag, "AddBoundary called");
526 int ret = Interop.Locator.AddBoundary(_handle, locationBoundary.GetHandle());
527 if ((LocationBoundError)ret != LocationBoundError.None)
529 Log.Error(Globals.LogTag, "Error Adding Boundary," + (LocationBoundError)ret);
530 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
535 /// Deletes a bound for a given locator.
537 /// <since_tizen> 3 </since_tizen>
538 /// <param name="locationBoundary"> The boundary object to be removed from the locator.</param>
539 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
540 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
541 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
542 public void RemoveBoundary(LocationBoundary locationBoundary)
544 Log.Info(Globals.LogTag, "RemoveBoundary called");
545 int ret = Interop.Locator.RemoveBoundary(_handle, locationBoundary.GetHandle());
546 if ((LocationBoundError)ret != LocationBoundError.None)
548 Log.Error(Globals.LogTag, "Error Removing Boundary," + (LocationBoundError)ret);
549 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
554 /// The overidden Dispose method of the IDisposable class.
556 /// <since_tizen> 3 </since_tizen>
557 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
558 public void Dispose()
561 GC.SuppressFinalize(this);
564 protected virtual void Dispose(bool disposing)
575 private void DestroyHandle()
577 int ret = Interop.Locator.Destroy(_handle);
578 if (((LocationError)ret != LocationError.None))
580 Log.Error(Globals.LogTag, "Error in Destroy handle, " + (LocationError)ret);
581 throw LocationErrorFactory.ThrowLocationException(ret);
586 /// The ServiceStateChanged event is invoked when the location service state is changed.
588 /// <since_tizen> 3 </since_tizen>
589 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
590 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
591 public event EventHandler<ServiceStateChangedEventArgs> ServiceStateChanged
595 Log.Info(Globals.LogTag, "ServiceStateChanged called");
596 if (_serviceStateChanged == null)
598 Log.Info(Globals.LogTag, "Calling function SetServiceStateChangedCallback");
599 SetServiceStateChangedCallback();
601 _serviceStateChanged += value;
605 Log.Info(Globals.LogTag, "Callback removed");
606 _serviceStateChanged -= value;
608 if (_serviceStateChanged == null)
610 Log.Info(Globals.LogTag, "Calling function UnSetServiceStateChangedCallback");
611 UnSetServiceStateChangedCallback();
616 private void SetServiceStateChangedCallback()
618 Log.Info(Globals.LogTag, "Calling Interop.LocatorEvent.SetServiceStateChangedCallback");
619 if (_serviceStateChangedCallback == null)
621 _serviceStateChangedCallback = (state, userData) =>
623 Log.Info(Globals.LogTag, "Inside ServiceStateChangedCallback");
624 _serviceStateChanged?.Invoke(this, new ServiceStateChangedEventArgs(state));
628 int ret = Interop.LocatorEvent.SetServiceStateChangedCallback(_handle, _serviceStateChangedCallback, IntPtr.Zero);
629 if (((LocationError)ret != LocationError.None))
631 Log.Error(Globals.LogTag, "Error in Setting Service State Changed Callback," + (LocationError)ret);
632 throw LocationErrorFactory.ThrowLocationException(ret);
636 private void UnSetServiceStateChangedCallback()
638 Log.Info(Globals.LogTag, "Calling Interop.LocatorEvent.UnSetServiceStateChangedCallback");
639 int ret = Interop.LocatorEvent.UnSetServiceStateChangedCallback(_handle);
640 if (((LocationError)ret != LocationError.None))
642 Log.Error(Globals.LogTag, "Error in UnSetting Service State Changed Callback," + (LocationError)ret);
643 throw LocationErrorFactory.ThrowLocationException(ret);
648 /// The ZoneChanged event is invoked when the previously set boundary area is entered or left.
650 /// <since_tizen> 3 </since_tizen>
651 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
652 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
653 public event EventHandler<ZoneChangedEventArgs> ZoneChanged
657 Log.Info(Globals.LogTag, "ZoneChanged called");
658 if (_zoneChanged == null)
660 Log.Info(Globals.LogTag, "Calling function SetZoneChangedCallback");
661 SetZoneChangedCallback();
663 _zoneChanged += value;
667 Log.Info(Globals.LogTag, "Callback removed");
668 _zoneChanged -= value;
670 if (_zoneChanged == null)
672 Log.Info(Globals.LogTag, "Calling function UnSetZoneChangedCallback");
673 UnSetZoneChangedCallback();
678 private void SetZoneChangedCallback()
680 Log.Info(Globals.LogTag, "Inside SetZoneChangedCallback");
681 if (_zoneChangedCallback == null)
683 _zoneChangedCallback = (state, latitude, longitude, altitude, timestamp, userData) =>
685 Log.Info(Globals.LogTag, "Inside ZoneChangedCallback");
686 DateTime timeStamp = DateTime.Now;
689 DateTime start = DateTime.SpecifyKind(new DateTime(1970, 1, 1).AddSeconds(timestamp), DateTimeKind.Utc);
690 timeStamp = start.ToLocalTime();
692 _zoneChanged?.Invoke(this, new ZoneChangedEventArgs(state, latitude, longitude, altitude, timeStamp));
696 int ret = Interop.LocatorEvent.SetZoneChangedCallback(_handle, _zoneChangedCallback, IntPtr.Zero);
697 if (((LocationError)ret != LocationError.None))
699 Log.Error(Globals.LogTag, "Error in Setting Zone Changed Callback," + (LocationError)ret);
700 throw LocationErrorFactory.ThrowLocationException(ret);
704 private void UnSetZoneChangedCallback()
706 Log.Info(Globals.LogTag, "Inside UnSetZoneChangedCallback");
707 int ret = Interop.LocatorEvent.UnSetZoneChangedCallback(_handle);
708 if (((LocationError)ret != LocationError.None))
710 Log.Error(Globals.LogTag, "Error in UnSetting Zone Changed Callback," + (LocationError)ret);
715 /// The SetttingChanged event is raised when the location setting is changed.
717 /// <since_tizen> 3 </since_tizen>
718 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
719 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
720 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
721 public event EventHandler<SettingChangedEventArgs> SettingChanged
725 Log.Info(Globals.LogTag, "Adding SettingChanged EventHandler");
726 if (_settingChanged == null)
728 Log.Info(Globals.LogTag, "Calling function SetSettingChangedCallback");
729 SetSettingChangedCallback();
731 _settingChanged += value;
735 Log.Info(Globals.LogTag, "Removing SettingChanged EventHandler");
736 _settingChanged -= value;
738 if (_settingChanged == null)
740 Log.Info(Globals.LogTag, "Calling function UnSetSettingChangedCallback");
741 UnSetSettingChangedCallback();
746 private void SetSettingChangedCallback()
748 Log.Info(Globals.LogTag, "Calling SetSettingChangedCallback");
749 if (_settingChangedCallback == null)
751 _settingChangedCallback = (method, enable, userData) =>
753 Log.Info(Globals.LogTag, "Calling SettingChangedCallback");
754 _settingChanged?.Invoke(this, new SettingChangedEventArgs(method, enable));
758 int ret = Interop.LocatorEvent.SetSettingChangedCallback((int)_locationType, _settingChangedCallback, IntPtr.Zero);
759 if (((LocationError)ret != LocationError.None))
761 Log.Error(Globals.LogTag, "Error in Setting Changed Callback," + (LocationError)ret);
762 throw LocationErrorFactory.ThrowLocationException(ret);
766 private void UnSetSettingChangedCallback()
768 Log.Info(Globals.LogTag, "Calling UnSetSettingChangedCallback");
769 int ret = Interop.LocatorEvent.UnSetSettingChangedCallback((int)_locationType);
770 if (((LocationError)ret != LocationError.None))
772 Log.Error(Globals.LogTag, "Error in Unsetting Setting's Callback," + (LocationError)ret);
773 throw LocationErrorFactory.ThrowLocationException(ret);
778 /// The DistanceBasedLocationChanged event is raised with the updated location information.
779 /// The callback will be invoked at a minimum interval or minimum distance with the updated position information.
781 /// <since_tizen> 3 </since_tizen>
782 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
783 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
784 public event EventHandler<LocationChangedEventArgs> DistanceBasedLocationChanged
788 Log.Info(Globals.LogTag, "Adding DistanceBasedLocationChanged EventHandler");
789 //if (_distanceBasedLocationChanged == null)
791 Log.Info(Globals.LogTag, "Calling function SetDistanceBasedLocationChangedCallback");
792 SetDistanceBasedLocationChangedCallback();
794 _distanceBasedLocationChanged += value;
798 Log.Info(Globals.LogTag, "Removing DistanceBasedLocationChanged EventHandler");
799 _distanceBasedLocationChanged -= value;
801 if (_distanceBasedLocationChanged == null)
803 Log.Info(Globals.LogTag, "Calling function UnSetDistanceBasedLocationChangedCallback");
804 UnSetDistanceBasedLocationChangedCallback();
809 private void SetDistanceBasedLocationChangedCallback()
811 Log.Info(Globals.LogTag, "SetDistanceBasedLocationChangedCallback");
812 if (_distanceBasedLocationChangedCallback == null) {
813 _distanceBasedLocationChangedCallback = (latitude, longitude, altitude, speed, direction, accuracy, timestamp, userData) =>
815 Log.Info(Globals.LogTag, "DistanceBasedLocationChangedCallback #1");
816 Location location = new Location(latitude, longitude, altitude, speed, direction, accuracy, timestamp);
817 Log.Info(Globals.LogTag, "DistanceBasedLocationChangedCallback #2");
818 _distanceBasedLocationChanged?.Invoke(this, new LocationChangedEventArgs(location));
819 Log.Info(Globals.LogTag, "DistanceBasedLocationChangedCallback #3");
823 int ret = Interop.LocatorEvent.SetDistanceBasedLocationChangedCallback(_handle, _distanceBasedLocationChangedCallback, _stayInterval, _distance, IntPtr.Zero);
824 if (((LocationError)ret != LocationError.None))
826 Log.Error(Globals.LogTag, "Error in Setting Distance based location changed Callback," + (LocationError)ret);
827 throw LocationErrorFactory.ThrowLocationException(ret);
831 private void UnSetDistanceBasedLocationChangedCallback()
833 Log.Info(Globals.LogTag, "UnSetDistanceBasedLocationChangedCallback");
834 int ret = Interop.LocatorEvent.UnSetDistanceBasedLocationChangedCallback(_handle);
835 if (((LocationError)ret != LocationError.None))
837 Log.Error(Globals.LogTag, "Error in UnSetting Distance based location changed Callback," + (LocationError)ret);
838 throw LocationErrorFactory.ThrowLocationException(ret);
840 _distanceBasedLocationChanged = null;
844 /// The LocationUpdated event is raised at defined intervals of time with the updated location information.
845 /// The callback will be invoked periodically.
847 /// <since_tizen> 3 </since_tizen>
848 /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
849 /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
850 public event EventHandler<LocationChangedEventArgs> LocationChanged
854 Log.Info(Globals.LogTag, "Adding LocationChanged EventHandler");
855 if (_batchPeriod > 0 && _batchPeriod > _batchInterval)
857 Log.Info(Globals.LogTag, "Calling function SetLocationBatchCallback");
858 SetLocationBatchCallback();
862 Log.Info(Globals.LogTag, "Calling function SetLocationChangedCallback");
863 SetLocationChangedCallback();
865 _locationChanged += value;
869 Log.Info(Globals.LogTag, "Removing LocationChanged EventHandler");
870 _locationChanged -= value;
872 if (_locationChanged == null)
874 if (_batchPeriod > 0 && _batchPeriod > _batchInterval)
876 Log.Info(Globals.LogTag, "Calling function UnSetLocationBatchCallback");
877 UnSetLocationBatchCallback();
881 Log.Info(Globals.LogTag, "Calling function UnSetLocationChangedCallback");
882 UnSetLocationChangedCallback();
888 private void SetLocationChangedCallback()
890 Log.Info(Globals.LogTag, "Calling SetLocationChangedCallback");
892 if (_locationChangedCallback == null) {
893 _locationChangedCallback = (latitude, longitude, altitude, speed, direction, accuracy, timestamp, userData) =>
895 Log.Info(Globals.LogTag, "LocationChangedCallback has been called");
896 Location location = new Location(latitude, longitude, altitude, speed, direction, accuracy, timestamp);
897 _location = location;
898 _locationChanged?.Invoke(this, new LocationChangedEventArgs(location));
902 int ret = Interop.LocatorEvent.SetLocationChangedCallback(_handle, _locationChangedCallback, _interval, IntPtr.Zero);
903 if (((LocationError)ret != LocationError.None))
905 Log.Error(Globals.LogTag, "Error in Setting location changed Callback," + (LocationError)ret);
906 throw LocationErrorFactory.ThrowLocationException(ret);
910 private void UnSetLocationChangedCallback()
912 Log.Info(Globals.LogTag, "Calling UnSetLocationChangedCallback");
913 int ret = Interop.LocatorEvent.UnSetLocationChangedCallback(_handle);
914 if (((LocationError)ret != LocationError.None))
916 Log.Error(Globals.LogTag, "Error in UnSetting location changed Callback," + (LocationError)ret);
917 throw LocationErrorFactory.ThrowLocationException(ret);
921 private void SetLocationBatchCallback()
923 Log.Info(Globals.LogTag, "Calling SetLocationBatchCallback");
925 if (_locationBatchCallback == null) {
926 _locationBatchCallback = (batch_size, userData) =>
928 Log.Info(Globals.LogTag, "LocationBatchCallback has been called, size : " + batch_size);
930 _locationBatchGetCallback = (latitude, longitude, altitude, speed, direction, horizontal, vertical, timestamp, batchUserData) =>
932 Log.Info(Globals.LogTag, "GetLocationBatch has been called");
933 Location location = new Location(latitude, longitude, altitude, speed, direction, horizontal, timestamp);
934 _location = location;
935 _locationChanged?.Invoke(this, new LocationChangedEventArgs(location));
938 ret = Interop.LocatorEvent.GetLocationBatch(_handle, _locationBatchGetCallback, IntPtr.Zero);
939 if (((LocationError)ret != LocationError.None))
941 Log.Error(Globals.LogTag, "Error in Setting location batch Callback," + (LocationError)ret);
942 throw LocationErrorFactory.ThrowLocationException(ret);
947 ret = Interop.LocatorEvent.SetLocationBatchCallback(_handle, _locationBatchCallback, _batchInterval, _batchPeriod, IntPtr.Zero);
948 if (((LocationError)ret != LocationError.None))
950 Log.Error(Globals.LogTag, "Error in Setting location batch Callback," + (LocationError)ret);
951 throw LocationErrorFactory.ThrowLocationException(ret);
955 private void UnSetLocationBatchCallback()
957 Log.Info(Globals.LogTag, "Calling UnSetLocationBatchCallback");
958 int ret = Interop.LocatorEvent.UnSetLocationBatchCallback(_handle);
959 if (((LocationError)ret != LocationError.None))
961 Log.Error(Globals.LogTag, "Error in UnSetting location batch Callback," + (LocationError)ret);
962 throw LocationErrorFactory.ThrowLocationException(ret);