/* * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; namespace Tizen.Location.Geofence { /// /// The Geofence Manager API provides service related to geofence (geo-fence). /// Geofence is a virtual perimeter for a real-world geographic area. /// This API provides functions to set geofence with a geopoint, MAC address of Wi-Fi, and Bluetooth address. /// Also, notifications on events like changing in service status are provided. /// There are two kinds of places and fences: /// /// Public places and fences are created by the MyPlace application that can be used by all applications. /// Private places and fences are created by the specified application that can be used by the same application. /// /// Notifications can be received about the following events: /// /// Zone in when a device enters a specific area. /// Zone out when a device exits a specific area. /// Results and errors for each event requested to the geofence module. /// /// /// 3 public class GeofenceManager : IDisposable { private bool _disposed = false; internal IntPtr Handle { get; set; } /// /// Creates a new Geofence manager. /// /// 3 /// In case of out of memory condition. /// In case of any system error. /// In case the geofence is not supported. public GeofenceManager() { IntPtr handle; GeofenceError ret = (GeofenceError) Interop.GeofenceManager.Create(out handle); if(ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to create Geofence Manager instance"); } Handle = handle; } /// /// The destructor of the GeofenceManager class. /// /// 3 ~GeofenceManager() { Dispose(false); } /// /// Checks whether the Geofence manager is available or not. /// /// 3 public static bool IsSupported { get { bool ret = false; GeofenceError res= (GeofenceError)Interop.GeofenceManager.IsSupported(out ret); if(res != GeofenceError.None) { Tizen.Log.Error(GeofenceErrorFactory.LogTag, "Failed to get IsSupported feature for Geofence manager"); } return ret; } } /// /// Starts the geofencing service. /// /// 3 /// The specified geofence ID. /// http://tizen.org/privilege/location /// /// When the location service is enabled, the StateChanged event is invoked and the service starts. /// /// In case of an invalid parameter. /// In case of any system error. /// In case privileges are not defined. /// In case the geofence is not supported. public void Start(int geofenceId) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.Start(Handle, geofenceId); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to start service for " + geofenceId); } } /// /// Stops the geofenceing service. /// /// 3 /// The specified geofence ID. /// http://tizen.org/privilege/location /// /// This function initiates the process of stopping the service. /// You can stop and start the Geofence manager as needed. /// /// In case of an invalid parameter. /// In case of any system error. /// In case privileges are not defined. /// In case the geofence is not supported. public void Stop(int geofenceId) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.Stop(Handle, geofenceId); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to stop service for " + geofenceId); } } private static readonly Interop.GeofenceManager.StateChangedCallback s_stateChangedCallback = (int fenceId, GeofenceState state, IntPtr data) => { GeofenceStateEventArgs evenArgs = new GeofenceStateEventArgs(fenceId, state); s_stateChanged?.Invoke(null, evenArgs); return true; }; private static event EventHandler s_stateChanged = null; /// /// Invokes when a device enters or exits the given geofence if this event is registered. /// /// 3 /// /// Call to Start() will invoke this event. /// /// In case the feature is not supported. public event EventHandler StateChanged { add { if(s_stateChanged == null) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.SetStateChangedCB(Handle, s_stateChangedCallback, IntPtr.Zero); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to register state change callback"); } } s_stateChanged += value; } remove { s_stateChanged -= value; if (s_stateChanged == null) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.UnsetStateChangedCB(Handle); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to unregister state change callback"); } } } } private static readonly Interop.GeofenceManager.ProximityStateChangedCallback s_proximityChangedCallback = (int fenceId, ProximityState state, ProximityProvider provider, IntPtr data) => { ProximityStateEventArgs evenArgs = new ProximityStateEventArgs(fenceId, state, provider); s_proximityChanged?.Invoke(null, evenArgs); return true; }; private static event EventHandler s_proximityChanged; /// /// Called when the proximity state of a device is changed. /// /// 3 /// /// Call to Start() will invoke this event. /// /// In case the feature is not supported. public event EventHandler ProximityChanged { add { if (s_proximityChanged == null) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.SetProximityStateCB(Handle, s_proximityChangedCallback, IntPtr.Zero); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to register proximity change callback"); } s_proximityChanged += value; } } remove { s_proximityChanged -= value; if (s_proximityChanged == null) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.UnsetProximityStateCB(Handle); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to un register proximity change callback"); } } } } private static readonly Interop.GeofenceManager.GeofenceEventCallback s_geofenceEventCallback = (int placeId, int fenceId, GeofenceError error, GeofenceEventType eventType, IntPtr data) => { GeofenceResponseEventArgs evenArgs = new GeofenceResponseEventArgs(placeId, fenceId, error, eventType); s_geofenceEventChanged?.Invoke(null, evenArgs); return true; }; private static event EventHandler s_geofenceEventChanged; /// /// Called when some event occurs in the geofence and the place, such as add, update, etc.. /// The events of public geofence is also received if there are public geofences. /// /// 3 /// /// Call to Start() will invoke this event. /// The value of place_id or geofence_id is -1 when the place ID or geofence ID is not assigned. /// /// In case the feature is not supported. public event EventHandler GeofenceEventChanged { add { if (s_geofenceEventChanged == null) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.SetGeofenceEventCB(Handle, s_geofenceEventCallback, IntPtr.Zero); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to register geofence event change callback"); } s_geofenceEventChanged += value; } } remove { s_geofenceEventChanged -= value; if (s_geofenceEventChanged == null) { GeofenceError ret = (GeofenceError)Interop.GeofenceManager.UnsetGeofenceEventCB(Handle); if (ret != GeofenceError.None) { throw GeofenceErrorFactory.CreateException(ret, "Failed to unregister geofence event change callback"); } } } } /// /// The overloaded Dispose API for destroying the GeofenceManager handle. /// /// 3 public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose. /// /// 3 protected virtual void Dispose(bool disposing) { if (_disposed) return; if (Handle != IntPtr.Zero) { Interop.GeofenceManager.Destroy(Handle); Handle = IntPtr.Zero; } _disposed = true; } } }