Add Internal Notification Response Event handler (#3178)
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.Notification / Tizen.Applications.Notifications / NotificationManager.cs
1 /*
2  * Copyright (c) 2017 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 namespace Tizen.Applications.Notifications
18 {
19     using System;
20     using System.ComponentModel;
21
22     /// <summary>
23     /// NotificationManager class to post, update, delete, and get notification.
24     /// </summary>
25     /// <since_tizen> 3 </since_tizen>
26     public static class NotificationManager
27     {
28         private static event EventHandler<NotificationResponseEventArgs> ResponseEventHandler;
29
30         private static Interop.Notification.ResponseEventCallback responseEventCallback;
31
32         private static void ResponseEventCallback(IntPtr ptr, int type, IntPtr userData)
33         {
34             IntPtr cloned;
35             NotificationError ret = Interop.Notification.Clone(ptr, out cloned);
36             if (ret != NotificationError.None)
37             {
38                 Log.Error(Notification.LogTag, "Fail to clone notification : " + ret.ToString());
39                 return;
40             }
41
42             NotificationResponseEventArgs eventArgs = new NotificationResponseEventArgs();
43             eventArgs.EventType = (NotificationResponseEventType)type;
44             eventArgs.Notification = new Notification
45             {
46                 Handle = new NotificationSafeHandle(cloned, true)
47             }.Build();
48             ResponseEventHandler?.Invoke(null, eventArgs);
49         }
50
51         /// <summary> 
52         /// The event handler for receiving a response event from the notification viewers
53         /// </summary>
54         /// <since_tizen> 8 </since_tizen>
55         [EditorBrowsable(EditorBrowsableState.Never)]
56         public static event EventHandler<NotificationResponseEventArgs> ResponseReceived
57         {
58             add
59             {
60                 if (responseEventCallback == null)
61                 {
62                     responseEventCallback = new Interop.Notification.ResponseEventCallback(ResponseEventCallback);
63                 }
64                 
65                 ResponseEventHandler += value;
66             }
67
68             remove
69             {
70                 if (ResponseEventHandler != null && ResponseEventHandler.GetInvocationList().Length > 0)
71                 {
72                     ResponseEventHandler -= value;
73                 }
74             }
75         }
76
77         /// <summary>
78         /// Posts a new notification.
79         /// </summary>
80         /// <param name="notification">Notification to post.</param>
81         /// <exception cref="ArgumentException">Thrown when an argument is invalid.</exception>
82         /// <exception cref="UnauthorizedAccessException">Thrown in case of a permission is denied.</exception>
83         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
84         /// <example>
85         /// <code>
86         /// Notification notification = new Notification
87         /// {
88         ///     Title = "title",
89         ///     Content = "content",
90         ///     Icon = "absolute icon path",
91         ///     Tag = "first notification"
92         /// };
93         ///
94         /// Notification.AccessorySet accessory = new Notification.AccessorySet
95         /// {
96         ///     SoundOption = AccessoryOption.On,
97         ///     CanVibrate = true
98         /// };
99         /// notification.Accessory = accessory;
100         ///
101         ///     // do something
102         ///
103         /// NotificationManager.Post(notification);
104         /// </code>
105         /// </example>
106         /// <privilege>http://tizen.org/privilege/notification</privilege>
107         /// <since_tizen> 3 </since_tizen>
108         public static void Post(Notification notification)
109         {
110             if (notification == null)
111             {
112                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to post method");
113             }
114
115             notification.Make();
116
117             if (ResponseEventHandler != null && ResponseEventHandler.GetInvocationList().Length > 0)
118             {
119                 NotificationError ret = Interop.Notification.PostWithEventCallback(notification.Handle, responseEventCallback, IntPtr.Zero);
120                 if (ret != NotificationError.None)
121                 {
122                     throw NotificationErrorFactory.GetException(ret, "post notification with event callback failed");
123                 }
124             }
125             else
126             {
127                 NotificationError ret = Interop.Notification.Post(notification.Handle);
128                 if (ret != NotificationError.None)
129                 {
130                     throw NotificationErrorFactory.GetException(ret, "post notification failed");
131                 }
132             }   
133
134             int priv_id, group_id;
135             Interop.Notification.GetID(notification.Handle, out group_id, out priv_id);
136             notification.PrivID = priv_id;
137         }
138
139         /// <summary>
140         /// Updates a posted notification.
141         /// </summary>
142         /// <param name="notification">Notification to update.</param>
143         /// <exception cref="ArgumentException">Thrown when an argument is invalid.</exception>
144         /// <exception cref="UnauthorizedAccessException">Thrown in case of a permission is denied.</exception>
145         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
146         /// <example>
147         /// <code>
148         /// string tag = "first tag";
149         ///
150         /// Notification notification = new Notification
151         /// {
152         ///     Title = "title",
153         ///     Content = "content",
154         ///     Icon = "absolute icon path",
155         ///     Tag = tag
156         /// };
157         ///
158         /// Notification.AccessorySet accessory = new Notification.AccessorySet
159         /// {
160         ///     LedOption = AccessoryOption.On,
161         ///     VibrationOption = AccessoryOption.Custom,
162         ///     VibrationPath = "vibration absolute path"
163         /// }
164         /// notification.Accessory = accessory;
165         ///
166         /// NotificationManager.Post(notification);
167         ///
168         ///     // do something
169         ///
170         /// Notification loadNotification = NotificationManager.Load(tag);
171         ///
172         /// loadNotification.Progress = new ProgressType(ProgressCategory.Percent, 0.0. 100.0);
173         ///
174         /// Thread thread = new Thread(new ParameterizedThreadStart(UpdateProgress));
175         /// thread.IsBackground = true;
176         /// thread.Start(notification);
177         ///
178         ///   ...
179         ///
180         /// static void UpdateProgress(Object obj)
181         /// {
182         ///     Notification notification = (Notification)obj;
183         ///
184         ///     for (double current = 1.0; current &lt;= 100.0; current = current + 1.0)
185         ///     {
186         ///         notification.Progress.ProgressCurrent = current;
187         ///         NotificationManager.Update(notification);
188         ///         Thread.Sleep(300);
189         ///     }
190         /// }
191         /// </code>
192         /// </example>
193         /// <privilege>http://tizen.org/privilege/notification</privilege>
194         /// <pre>
195         /// Post method should be called on the notification object.
196         /// </pre>
197         /// <since_tizen> 3 </since_tizen>
198         public static void Update(Notification notification)
199         {
200             if (notification == null || notification.Handle == null || notification.Handle.IsInvalid)
201             {
202                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to post method");
203             }
204
205             notification.Make();
206             NotificationError ret = Interop.Notification.Update(notification.Handle);
207             if (ret != NotificationError.None)
208             {
209                 throw NotificationErrorFactory.GetException(ret, "update notification failed");
210             }
211         }
212
213         /// <summary>
214         /// Deletes a posted notification.
215         /// </summary>
216         /// <param name="notification">Notification to remove.</param>
217         /// <exception cref="ArgumentException">Thrown when an argument is invalid.</exception>
218         /// <exception cref="UnauthorizedAccessException">Thrown in case of a permission is denied.</exception>
219         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
220         /// <example>
221         /// <code>
222         /// Notification notification = new Notification
223         /// {
224         ///     Title = "title",
225         ///     Content = "content",
226         ///     Icon = "absolute icon path",
227         ///     Tag = "first notification"
228         /// };
229         /// NotificationManager.Post(notification);
230         ///
231         ///     // do something
232         ///
233         /// NotificationManager.Delete(notification);
234         /// </code>
235         /// </example>
236         /// <privilege>http://tizen.org/privilege/notification</privilege>
237         /// <pre>
238         /// Post method should be called on the notification object.
239         /// </pre>
240         /// <since_tizen> 3 </since_tizen>
241         public static void Delete(Notification notification)
242         {
243             if (notification == null || notification.Handle == null || notification.Handle.IsInvalid)
244             {
245                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to post method");
246             }
247
248             NotificationError ret = Interop.Notification.Delete(notification.Handle);
249             if (ret != NotificationError.None)
250             {
251                 throw NotificationErrorFactory.GetException(ret, "delete notification failed");
252             }
253         }
254
255         /// <summary>
256         /// Removes all posted notifications of calling application.
257         /// </summary>
258         /// <exception cref="UnauthorizedAccessException">Thrown in case of a permission is denied.</exception>
259         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
260         /// <example>
261         /// <code>
262         /// Notification firstNotification = new Notification
263         /// {
264         ///     Title = "title",
265         ///     Content = "content",
266         ///     Icon = "absolute icon path",
267         ///     Tag = "first notification"
268         /// };
269         /// NotificationManager.Post(firstNotification);
270         ///
271         /// Notification secondNotification = new Notification
272         /// {
273         ///     Title = "title",
274         ///     Content = "content",
275         ///     Icon = "absolute icon path",
276         ///     Tag = "second notification"
277         /// };
278         /// NotificationManager.Post(secondNotification);
279         /// NotificationManager.DeleteAll();
280         /// </code>
281         /// </example>
282         /// <privilege>http://tizen.org/privilege/notification</privilege>
283         /// <since_tizen> 3 </since_tizen>
284         public static void DeleteAll()
285         {
286             NotificationError ret;
287
288             ret = Interop.Notification.DeleteAll((int)NotificationType.Basic);
289             if (ret != NotificationError.None)
290             {
291                 throw NotificationErrorFactory.GetException(ret, "delete all notifications failed of Noti type");
292             }
293
294             ret = Interop.Notification.DeleteAll((int)NotificationType.Ongoing);
295             if (ret != NotificationError.None)
296             {
297                 throw NotificationErrorFactory.GetException(ret, "delete all notifications failed of Ongoing type");
298             }
299         }
300
301         /// <summary>
302         /// Searches for a posted notification which has the specified tag and has not been deleted yet.
303         /// </summary>
304         /// <remarks>
305         /// Load method should be called only for notifications, which have been posted using the NotificationManager.Post method.
306         /// If two or more notifications share the same tag, the notification posted most recently is returned.
307         /// </remarks>
308         /// <param name="tag">Tag used to query.</param>
309         /// <returns>Notification Object with specified tag.</returns>
310         /// <exception cref="ArgumentException">Throwing the same exception when argument is invalid and when the tag does not exist is misleading.</exception>
311         /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception>
312         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
313         /// <example>
314         /// <code>
315         /// Notification notification = new Notification
316         /// {
317         ///     Title = "title",
318         ///     Content = "content",
319         ///     Icon = "absolute icon path",
320         ///     Tag = "first notification"
321         /// };
322         /// NotificationManager.Post(notification);
323         ///
324         ///     // do someting
325         ///
326         /// Notification loadNotification = NotificationManager.Load("first notification");
327         /// </code>
328         /// </example>
329         /// <privilege>http://tizen.org/privilege/notification</privilege>
330         /// <since_tizen> 3 </since_tizen>
331         public static Notification Load(string tag)
332         {
333             IntPtr ptr = IntPtr.Zero;
334
335             if (string.IsNullOrEmpty(tag))
336             {
337                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
338             }
339
340             ptr = Interop.Notification.Load(tag);
341
342             if (ptr == IntPtr.Zero)
343             {
344                 NotificationError ret = (NotificationError)Tizen.Internals.Errors.ErrorFacts.GetLastResult();
345                 Log.Error(Notification.LogTag, "unable to load Notification : " + ret.ToString());
346                 if (ret == NotificationError.DbError)
347                 {
348                     throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "the tag does not exist");
349                 }
350                 else
351                 {
352                     throw NotificationErrorFactory.GetException(ret, "unable to load Notification");
353                 }
354             }
355
356             Notification notification = new Notification
357             {
358                 Handle = new NotificationSafeHandle(ptr, true)
359             }.Build();
360
361             return notification;
362         }
363
364         /// <summary>
365         /// Saves a notification template to the notification database.
366         /// </summary>
367         /// <param name="notification">Notification to save as template.</param>
368         /// <param name="name">Template name.</param>
369         /// <exception cref="ArgumentException">Thrown when an argument is invalid.</exception>
370         /// <exception cref="UnauthorizedAccessException">Thrown in case of a permission is denied.</exception>
371         /// <exception cref="InvalidOperationException">Thrown when it can't be saved as a template.</exception>
372         /// <example>
373         /// <code>
374         /// Notification notification = new Notification
375         /// {
376         ///     Title = "title",
377         ///     Content = "content",
378         ///     Icon = "absolute icon path",
379         ///     Tag = "first notification"
380         /// };
381         ///
382         /// Notification.Accessory accessory = new Notification.Accessory
383         /// {
384         ///     LedOption = AccessoryOption.On,
385         ///     VibrationOption = AccessoryOption.Custom,
386         ///     VibrationPath = "vibration absolute path"
387         /// }
388         /// notification.setAccessory(accessory);
389         ///
390         ///     // do something
391         ///
392         /// NotificationManager.Post(notification);
393         ///
394         /// Notification.LockStyle style = new Notification.LockStyle
395         /// {
396         ///     IconPath = "icon path",
397         ///     ThumbnailPath = "Thumbnail path"
398         /// }
399         /// notification.AddStyle(style);
400         /// NotificationManager.SaveTemplate(notification, "firstTemplate");
401         /// </code>
402         /// </example>
403         /// <privilege>http://tizen.org/privilege/notification</privilege>
404         /// <since_tizen> 3 </since_tizen>
405         public static void SaveTemplate(Notification notification, string name)
406         {
407             if (notification == null || string.IsNullOrEmpty(name))
408             {
409                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to save template");
410             }
411
412             notification.Make();
413
414             NotificationError ret = Interop.Notification.SaveTemplate(notification.Handle, name);
415             if (ret != NotificationError.None)
416             {
417                 throw NotificationErrorFactory.GetException(ret, "save as template failed");
418             }
419         }
420
421         /// <summary>
422         /// Loads a notification template from the notification database.
423         /// </summary>
424         /// <param name="name">Template name.</param>
425         /// <returns>Notification Object with inputted template name.</returns>
426         /// <exception cref="ArgumentException">Throwing the same exception when argument is invalid and when the template does not exist is misleading.</exception>
427         /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception>
428         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
429         /// <example>
430         /// <code>
431         /// Notification notification = new Notification
432         /// {
433         ///     Title = "title",
434         ///     Content = "content",
435         ///     Icon = "absolute icon path",
436         ///     Tag = "first notification"
437         /// };
438         ///
439         /// Notification.Accessory accessory = new Notification.Accessory
440         /// {
441         ///     LedOption = AccessoryOption.On,
442         ///     VibrationOption = AccessoryOption.Custom,
443         ///     VibrationPath = "vibration absolute path"
444         /// }
445         /// notification.setAccessory(accessory);
446         ///
447         ///     // do something
448         ///
449         /// NotificationManager.Post(notification);
450         ///
451         /// Notification.LockStyle style = new Notification.LockStyle
452         /// {
453         ///     IconPath = "icon path",
454         ///     ThumbnailPath = "Thumbnail path"
455         /// }
456         /// notification.AddStyle(style);
457         /// NotificationManager.SaveTemplate(notification, "firstTemplate");
458         /// Notification notificationTemplate = NotificationManager.LoadTemplate("firstTemplate");
459         /// </code>
460         /// </example>
461         /// <privilege>http://tizen.org/privilege/notification</privilege>
462         /// <since_tizen> 3 </since_tizen>
463         public static Notification LoadTemplate(string name)
464         {
465             IntPtr handle = IntPtr.Zero;
466
467             if (string.IsNullOrEmpty(name))
468             {
469                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to load template");
470             }
471
472             handle = Interop.Notification.LoadTemplate(name);
473             if (handle == IntPtr.Zero)
474             {
475                 NotificationError ret = (NotificationError)Tizen.Internals.Errors.ErrorFacts.GetLastResult();
476                 if (ret == NotificationError.DbError)
477                 {
478                     throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "the name does not exist");
479                 }
480                 else
481                 {
482                     throw NotificationErrorFactory.GetException(ret, "unable to create Notification from template");
483                 }
484             }
485
486             Notification notification = new Notification
487             {
488                 Handle = new NotificationSafeHandle(handle, true)
489             }.Build();
490
491             return notification;
492         }
493
494         /// <summary>
495         /// Gets notification block state.
496         /// </summary>
497         /// <remarks>
498         /// The user can set the notification block state in settings.
499         /// The block state indicates whether or not notifications can be posted.
500         /// Additionally, only notifications to the notification panel are allowed in "Do not disturb mode".
501         /// Sound, vibrate, and active notifications are blocked.
502         /// </remarks>
503         /// <returns>NotificationBlockState is a state if notification is posted.</returns>
504         /// <exception cref="UnauthorizedAccessException">Thrown in case of a permission is denied.</exception>
505         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
506         /// <privilege>http://tizen.org/privilege/notification</privilege>
507         /// <since_tizen> 3 </since_tizen>
508         public static NotificationBlockState GetBlockState()
509         {
510             NotificationBlockState state;
511             NotificationError ret;
512
513             ret = Interop.Notification.GetBlockState(out state);
514             if (ret != NotificationError.None)
515             {
516                 throw NotificationErrorFactory.GetException(ret, "GetBlockState failed");
517             }
518
519             Log.Info(Notification.LogTag, "Current block state is " + state.ToString());
520             return state;
521         }
522
523         /// <summary>
524         /// Make a NotificationSafeHandle from Notification.
525         /// </summary>
526         /// <param name="notification">The Notification class.</param>
527         /// <returns>The NotificationSafeHandle class.</returns>
528         /// <exception cref="ArgumentException">Thrown when an argument is invalid.</exception>
529         /// <since_tizen> 3 </since_tizen>
530         [EditorBrowsable(EditorBrowsableState.Never)]
531         public static NotificationSafeHandle MakeNotificationSafeHandle(Notification notification)
532         {
533             if (notification == null)
534             {
535                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid notification object");
536             }
537
538             notification.Make();
539
540             return notification.Handle;
541         }
542
543         /// <summary>
544         /// Make a Notification from NotificationSafeHandle.
545         /// </summary>
546         /// <param name="handle">The NotificationSafeHandle class.</param>
547         /// <returns>The Notification class.</returns>
548         /// <exception cref="ArgumentException">Thrown when an argument is invalid.</exception>
549         /// <since_tizen> 3 </since_tizen>
550         [EditorBrowsable(EditorBrowsableState.Never)]
551         public static Notification MakeNotification(NotificationSafeHandle handle)
552         {
553             if (handle == null || handle.IsInvalid == true)
554             {
555                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "handle is invalid or null");
556             }
557
558             Notification notification = new Notification { Handle = handle }.Build();
559
560             return notification;
561         }
562     }
563 }