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