[TCSACR-43] change GeoFence to Geofence
[platform/core/csapi/geofence.git] / Tizen.Location.Geofence / Tizen.Location.Geofence / GeofenceManager.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 using System;
18
19 namespace Tizen.Location.Geofence
20 {
21     /// <summary>
22     /// This Geofence Manager API provides service related to geofence(geo-fence).
23     /// A geofence is a virtual perimeter for a real-world geographic area.
24     /// This API provides functions to set geofence with geopoint, MAC address of Wi-Fi and Bluetooth address.
25     /// And, notifications on events like changing in service status are provided.
26     /// There are two kinds of places and fences:
27     /// <list>
28     /// <item>Public places and fences that are created by MyPlace app can be used by all apps.</item>
29     /// <item>Private places and fences that are created by specified app can be used by the same app.</item>
30     /// </list>
31     /// Notifications can be received about the following events:
32     /// <list>
33     /// <item>Zone in when a device enters a specific area</item>
34     /// <item>Zone out when a device exits a specific area</item>
35     /// <item>Results and errors for each event requested to geofence module</item>
36     /// </list>
37     /// </summary>
38     public class GeofenceManager : IDisposable
39     {
40         private bool _disposed = false;
41
42         internal IntPtr Handle
43         {
44             get;
45             set;
46         }
47
48         /// <summary>
49         /// Creates a new geofence manager.
50         /// </summary>
51         /// <exception cref="OutOfMemoryException">Incase of OutOfMemory condition.</exception>
52         /// <exception cref="InvalidOperationException">Incase of any System error.</exception>
53         /// <exception cref="NotSupportedException">Incase of Geofence is not supported.</exception>
54         public GeofenceManager()
55         {
56             IntPtr handle;
57             GeofenceError ret = (GeofenceError) Interop.GeofenceManager.Create(out handle);
58             if(ret != GeofenceError.None)
59             {
60                 throw GeofenceErrorFactory.CreateException(ret, "Failed to create Geofence Manager instance");
61             }
62
63             Handle = handle;
64         }
65
66         ~GeofenceManager()
67         {
68             Dispose(false);
69         }
70
71         /// <summary>
72         /// Checks whether the geofence manager is available or not.
73         /// </summary>
74         public static bool IsSupported
75         {
76             get
77             {
78                 bool ret = false;
79                 GeofenceError res= (GeofenceError)Interop.GeofenceManager.IsSupported(out ret);
80                 if(res != GeofenceError.None)
81                 {
82                     Tizen.Log.Error(GeofenceErrorFactory.LogTag, "Failed to get IsSupported feature for Geofence manager");
83                 }
84
85                 return ret;
86             }
87         }
88
89         /// <summary>
90         /// Starts the geofencing service.
91         /// </summary>
92         /// <param name="geofenceId">The specified geofence id.</param>
93         /// <privilege>http://tizen.org/privilege/location</privilege>
94         /// <remarks>
95         /// When the location service is enabled, the StateChanged event is invoked and the service starts.
96         /// </remarks>
97         /// <exception cref="ArgumentException">Incase of Invalid parameter.</exception>
98         /// <exception cref="InvalidOperationException">Incase of any System error.</exception>
99         /// <exception cref="UnauthorizedAccessException">Incase of Privileges are not defined.</exception>
100         /// <exception cref="NotSupportedException">Incase of Geofence is not supported.</exception>
101         public void Start(int geofenceId)
102         {
103             GeofenceError ret = (GeofenceError)Interop.GeofenceManager.Start(Handle, geofenceId);
104             if (ret != GeofenceError.None)
105             {
106                 throw GeofenceErrorFactory.CreateException(ret, "Failed to start service for "  + geofenceId);
107             }
108         }
109
110         /// <summary>
111         /// Stops the geofenceing service.
112         /// </summary>
113         /// <param name="geofenceId">The specified geofence id.</param>
114         /// <privilege>http://tizen.org/privilege/location</privilege>
115         /// <remarks>
116         /// This function initiates the process of stopping the service.
117         /// You can stop and start the geofence manager as needed.
118         /// </remarks>
119         /// <exception cref="ArgumentException">Incase of Invalid parameter.</exception>
120         /// <exception cref="InvalidOperationException">Incase of any System error.</exception>
121         /// <exception cref="UnauthorizedAccessException">Incase of Privileges are not defined.</exception>
122         /// <exception cref="NotSupportedException">Incase of Geofence is not supported.</exception>
123         public void Stop(int geofenceId)
124         {
125             GeofenceError ret = (GeofenceError)Interop.GeofenceManager.Stop(Handle, geofenceId);
126             if (ret != GeofenceError.None)
127             {
128                 throw GeofenceErrorFactory.CreateException(ret, "Failed to stop service for " + geofenceId);
129             }
130         }
131
132         private static readonly Interop.GeofenceManager.StateChangedCallback s_stateChangedCallback = (int fenceId, GeofenceState state, IntPtr data) =>
133          {
134              GeofenceStateEventArgs evenArgs = new GeofenceStateEventArgs(fenceId, state);
135              s_stateChanged?.Invoke(null, evenArgs);
136              return true;
137          };
138
139         private static event EventHandler<GeofenceStateEventArgs> s_stateChanged = null;
140
141         /// <summary>
142         /// Invokes when a device enters or exits the given geofence, If this event is registered.
143         /// </summary>
144         /// <remarks>
145         /// Call to Start() will invoke this event.
146         /// </remarks>
147         /// <exception cref="NotSupportedException">Incase of feature Not supported.</exception>
148         public event EventHandler<GeofenceStateEventArgs> StateChanged
149         {
150             add
151             {
152                 if(s_stateChanged == null)
153                 {
154                     GeofenceError ret = (GeofenceError)Interop.GeofenceManager.SetStateChangedCB(Handle, s_stateChangedCallback, IntPtr.Zero);
155                     if (ret != GeofenceError.None)
156                     {
157                         throw GeofenceErrorFactory.CreateException(ret, "Failed to register state change callback");
158                     }
159                 }
160                 s_stateChanged += value;
161             }
162             remove
163             {
164                 s_stateChanged -= value;
165                 if (s_stateChanged == null)
166                 {
167                     GeofenceError ret = (GeofenceError)Interop.GeofenceManager.UnsetStateChangedCB(Handle);
168                     if (ret != GeofenceError.None)
169                     {
170                         throw GeofenceErrorFactory.CreateException(ret, "Failed to unregister state change callback");
171                     }
172                 }
173             }
174         }
175
176         private static readonly Interop.GeofenceManager.ProximityStateChangedCallback s_proximityChangedCallback = (int fenceId, ProximityState state, ProximityProvider provider, IntPtr data) =>
177         {
178             ProximityStateEventArgs evenArgs = new ProximityStateEventArgs(fenceId, state, provider);
179             s_proximityChanged?.Invoke(null, evenArgs);
180             return true;
181         };
182
183         private static event EventHandler<ProximityStateEventArgs> s_proximityChanged;
184
185         /// <summary>
186         /// Called when a proximity state of device is changed.
187         /// </summary>
188         /// <remarks>
189         /// Call to Start() will invoke this event.
190         /// </remarks>
191         /// <exception cref="NotSupportedException">Incase of feature Not supported.</exception>
192         public event EventHandler<ProximityStateEventArgs> ProximityChanged
193         {
194             add
195             {
196                 if (s_proximityChanged == null)
197                 {
198                     GeofenceError ret = (GeofenceError)Interop.GeofenceManager.SetProximityStateCB(Handle, s_proximityChangedCallback, IntPtr.Zero);
199                     if (ret != GeofenceError.None)
200                     {
201                         throw GeofenceErrorFactory.CreateException(ret, "Failed to register proximity change callback");
202                     }
203                     s_proximityChanged += value;
204                 }
205             }
206             remove
207             {
208                 s_proximityChanged -= value;
209                 if (s_proximityChanged == null)
210                 {
211                     GeofenceError ret = (GeofenceError)Interop.GeofenceManager.UnsetProximityStateCB(Handle);
212                     if (ret != GeofenceError.None)
213                     {
214                         throw GeofenceErrorFactory.CreateException(ret, "Failed to un register proximity change callback");
215                     }
216                 }
217             }
218         }
219
220         private static readonly Interop.GeofenceManager.GeofenceEventCallback s_geofenceEventCallback = (int placeId, int fenceId, GeofenceError error, GeofenceEventType eventType, IntPtr data) =>
221         {
222             GeofenceResponseEventArgs evenArgs = new GeofenceResponseEventArgs(placeId, fenceId, error, eventType);
223             s_geofenceEventChanged?.Invoke(null, evenArgs);
224             return true;
225         };
226
227         private static event EventHandler<GeofenceResponseEventArgs> s_geofenceEventChanged;
228
229         /// <summary>
230         /// Called when the some event occurs in geofence and place such as add, update, etc..
231         /// The events of public geofence is also received if there are public geofences.
232         /// </summary>
233         /// <remarks>
234         /// Call to Start() will invoke this event.
235         /// The value of place_id or geofence_id is -1 when the place id or geofence id is not assigned.
236         /// </remarks>
237         /// <exception cref="NotSupportedException">Incase of feature Not supported.</exception>
238         public event EventHandler<GeofenceResponseEventArgs> GeofenceEventChanged
239         {
240             add
241             {
242                 if (s_geofenceEventChanged == null)
243                 {
244                     GeofenceError ret = (GeofenceError)Interop.GeofenceManager.SetGeofenceEventCB(Handle, s_geofenceEventCallback, IntPtr.Zero);
245                     if (ret != GeofenceError.None)
246                     {
247                         throw GeofenceErrorFactory.CreateException(ret, "Failed to register geofence event change callback");
248                     }
249                     s_geofenceEventChanged += value;
250                 }
251             }
252             remove
253             {
254                 s_geofenceEventChanged -= value;
255                 if (s_geofenceEventChanged == null)
256                 {
257                     GeofenceError ret = (GeofenceError)Interop.GeofenceManager.UnsetGeofenceEventCB(Handle);
258                     if (ret != GeofenceError.None)
259                     {
260                         throw GeofenceErrorFactory.CreateException(ret, "Failed to unregister geofence event change callback");
261                     }
262                 }
263             }
264         }
265
266         /// <summary>
267         /// Overloaded Dispose API for destroying the GeofenceManager Handle.
268         /// </summary>
269         public void Dispose()
270         {
271             Dispose(true);
272             GC.SuppressFinalize(this);
273         }
274
275         private void Dispose(bool disposing)
276         {
277             if (_disposed)
278                 return;
279
280             if (Handle != IntPtr.Zero)
281             {
282                 Interop.GeofenceManager.Destroy(Handle);
283                 Handle = IntPtr.Zero;
284             }
285
286             _disposed = true;
287         }
288     }
289 }