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