/* * Copyright (c) 2017 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. */ namespace Tizen.Applications.Notifications { using System; using System.Collections.Generic; using System.ComponentModel; /// /// This class contains common properties and methods of notifications. /// /// /// A notification is a message that is displayed on the notification area. /// It is created to notify information to the user through the application. /// This class helps you to provide method and property for creating notification object. /// public sealed partial class Notification : IDisposable { internal static readonly string LogTag = "Tizen.Applications.Notification"; private NotificationSafeHandle safeHandle; private bool disposed = false; private IDictionary styleDictionary; private IDictionary extraDataDictionary; private int count = 0; /// /// Initializes a new instance of the class. /// public Notification() { styleDictionary = new Dictionary(); extraDataDictionary = new Dictionary(); } /// /// Gets or sets the tag of notification. /// public string Tag { get; set; } = string.Empty; /// /// Gets or sets the title of notification. /// public string Title { get; set; } = string.Empty; /// /// Gets or sets the icon of notification. /// You should set an absolute path for an image file. /// public string Icon { get; set; } = string.Empty; /// /// Gets or sets the sub icon of notification. /// This SubIcon is displayed in Icon you set. /// You should set an absolute path for an image file. /// public string SubIcon { get; set; } = string.Empty; /// /// Gets or sets the content of notification. /// public string Content { get; set; } = string.Empty; /// /// Gets or sets a value indicating whether TimeStamp of the notification is Visible or not. /// Default to true. /// public bool IsTimeStampVisible { get; set; } = true; /// /// Gets or sets the TimeStamp of notification. /// /// /// If you don't set TimeStamp, it will set the value when the notification is posted. /// TimeStamp requires NotificationManager.Post() to be called. /// If you set IsVisibleTimeStamp property to false, TimeStamp is not visible in notification. /// public DateTime TimeStamp { get; set; } /// /// Gets or sets action, which is invoked when the notification is clicked. /// /// /// If you set it to null, the already set AppControl will be removed and nothing will happen when you click on notification. /// /// public AppControl Action { get; set; } /// /// Gets or sets count, which is displayed at the right side of the notification. /// /// /// You must set only positive number. /// If you set count to negative number, this property throws exception. /// /// Thrown when argument is invalid. public int Count { get { return count; } set { if (value < 0) { Log.Error(LogTag, "Count value is negative"); throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "The Count must be a positive integer."); } count = value; } } [EditorBrowsable(EditorBrowsableState.Never)] public bool IsOngoing { get; set; } = false; /// /// Gets or sets property. /// /// public NotificationProperty Property { get; set; } = NotificationProperty.None; /// /// Gets or sets object for display at notification. /// /// public ProgressType Progress { get; set; } /// /// Gets or sets which is included vibration, LED and sound option to be applied at notification. /// /// /// If you set it to null, the already set AccessorySet will be initialized. /// /// /// /// Notification notification = new Notification /// { /// Title = "Notification", /// Content = "Hello Tizen", /// Icon = "Icon path", /// Count = 3 /// }; /// /// Notification.AccessorySet accessory = new Notification.AccessorySet /// { /// SoundOption = AccessoryOption.Custom, /// SoundPath = "Sound File Path", /// IsVibration = true, /// LedOption = AccessoryOption.Custom, /// LedOnMs = 100; /// LedOffMs = 50; /// LedColor = Color.Lime /// }; /// /// notification.Accessory = accessory; /// /// NotificationManager.Post(notification); /// /// public AccessorySet Accessory { get; set; } /// /// Gets or sets a value indicating whether notification is displayed on the default viewer. /// If you set false and add style, you can see only style notification. /// public bool IsVisible { get; set; } = true; /// /// Gets or sets NotificationSafeHandle. /// internal NotificationSafeHandle Handle { get { return safeHandle; } set { if (value == null) { Log.Error(LogTag, "Invalid argument NotificationSafeHandle"); throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to set NotificationSafeHandle"); } safeHandle = value; } } /// /// Gets or sets private ID. /// internal int PrivID { get; set; } = -1; /// /// Method for adding various styles to be applied to notification. /// /// /// The user always see about valid notification style. If you add a style which is not supported in platform, /// this method has no effect. /// /// The style to be applied to notification. /// Thrown when argument is invalid. /// /// /// Notification notification = new Notification /// { /// Title = "Notification", /// Content = "Hello Tizen", /// Icon = "Icon path", /// Count = 3 /// }; /// /// Notification.LockStyle lockStyle = new Notification.LockStyle /// { /// IconPath = "Icon path", /// ThumbnailPath = "Thumbnail Path" /// }; /// /// notification.AddStyle(lockStyle); /// /// NotificationManager.Post(notification); /// /// public void AddStyle(StyleBase style) { if (style == null) { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered"); } if (styleDictionary.ContainsKey(style.Key) == true) { Log.Info(LogTag, "The Style is existed, so extender data is replaced"); styleDictionary.Remove(style.Key); styleDictionary.Add(style.Key, style); } else { styleDictionary.Add(style.Key, style); } } /// /// Method to remove style you already added. /// /// Type of notification style to be queried. /// Thrown when argument is invalid. public void RemoveStyle() where T : Notification.StyleBase, new() { T type = new T(); if (styleDictionary.ContainsKey(type.Key)) { styleDictionary.Remove(type.Key); } else { Log.Error(LogTag, "Sytle Can't be removed, there is no style matched input key"); throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered"); } } /// /// Method to get style you already added. /// /// Type of notification style to be queried. /// /// The Notification.Style object associated with the given style. /// /// Thrown when argument is invalid. public T GetStyle() where T : Notification.StyleBase, new() { T type = new T(); StyleBase style = null; styleDictionary.TryGetValue(type.Key, out style); if (style == null) { Log.Error(LogTag, "Invalid Style"); throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered"); } else { return style as T; } } /// /// Method to set extra data to add extra data. /// /// /// The type of extra data is bundle. /// /// The key of the extra data you want to add. /// The value you want to add. /// Thrown when argument is invalid. /// /// /// Notification notification = new Notification /// { /// Title = "Notification", /// Content = "Hello Tizen", /// Icon = "Icon path", /// }; /// /// Bundle bundle = new Bundle(); /// bundle.AddItem("key", "value"); /// /// notification.SetExtraData("firstKey", bundle); /// /// public void SetExtraData(string key, Bundle value) { if (value == null || value.SafeBundleHandle.IsInvalid || string.IsNullOrEmpty(key)) { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered"); } if (extraDataDictionary.ContainsKey(key) == true) { Log.Info(LogTag, "The key is existed, so extender data is replaced"); extraDataDictionary.Remove(key); extraDataDictionary.Add(key, value); } else { extraDataDictionary.Add(key, value); } } /// /// Method to remove extra you already added. /// /// /// The type of extra data is bundle. /// /// The key of the extra data to add. /// Thrown when argument is invalid. public void RemoveExtraData(string key) { if (string.IsNullOrEmpty(key)) { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered"); } if (extraDataDictionary.ContainsKey(key)) { extraDataDictionary.Remove(key); } else { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered"); } } /// /// Method to get extra data you already set. /// /// The key of the extra data to get. /// Bundle Object that include extra data /// Thrown when argument is invalid. public Bundle GetExtraData(string key) { if (string.IsNullOrEmpty(key)) { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered"); } Bundle bundle; if (extraDataDictionary.TryGetValue(key, out bundle) == false) { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered : " + key); } return bundle; } /// /// Releases any unmanaged resources used by this object. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } internal void Dispose(bool disposing) { if (disposed) { return; } if (disposing && Handle != null && Handle.IsInvalid == false) { Handle.Dispose(); } disposed = true; } internal IDictionary GetStyleDictionary() { return styleDictionary; } internal IDictionary GetextraDataDictionary() { return extraDataDictionary; } internal StyleBase GetStyle(string key) { if (string.IsNullOrEmpty(key)) { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "Key is null or empty"); } StyleBase style = null; bool ret = styleDictionary.TryGetValue(key, out style); if (ret == false) { throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "The Style object matched input key is not existed"); } return style; } internal void Make() { NotificationBinder.BindObject(this); foreach (string key in GetextraDataDictionary().Keys) { Log.Info(LogTag, "Start to bind Notification.ExtenderData to SafeHandle"); Interop.Notification.SetExtentionData(Handle, key, extraDataDictionary[key].SafeBundleHandle); } foreach (Notification.StyleBase style in styleDictionary.Values) { Log.Info(LogTag, "Start to bind Notification.Style to SafeHandle [" + style.Key + "]"); style.Make(this); } if (Accessory != null) { Log.Info(LogTag, "Start to bind Notification.AccessetSet to SafeHandle"); Accessory.Make(this); } if (Progress != null) { Log.Info(LogTag, "Start to bind Notification.Progress to SafeHandle"); Progress.Make(this); } } internal Notification Build() { IntPtr extention = IntPtr.Zero; IntPtr extentionBundlePtr = IntPtr.Zero; NotificationBinder.BindSafeHandle(this); Interop.Notification.GetExtentionBundle(Handle, out extention, out extentionBundlePtr); if (extention != IntPtr.Zero) { Bundle bundle = new Bundle(new SafeBundleHandle(extention, false)); foreach (string key in bundle.Keys) { if (key.StartsWith("_NOTIFICATION_EXTENSION_EVENT_")) continue; SafeBundleHandle sbh; Interop.Notification.GetExtentionData(Handle, key, out sbh); extraDataDictionary.Add(key, new Bundle(sbh)); } } ProgressBinder.BindSafeHandle(this); AccessorySetBinder.BindSafeHandle(this); IndicatorBinder.BindSafeHandle(this); ActiveBinder.BindSafeHandle(this); LockBinder.BindSafehandle(this); return this; } } }