private void NotifyNode(INotifiable source) { bool evaluating = true; var stack = new Stack <Tuple <INotifiable, int> >(); stack.Push(new Tuple <INotifiable, int>(source, 1)); while (stack.Count > 0) { var tuple = stack.Pop(); var node = tuple.Item1; var metaData = node.ExecutionMetaData; metaData.RemainingVisits -= tuple.Item2; if (metaData.RemainingVisits > 0) { continue; } INotificationResult result = null; if (evaluating || metaData.Results.Count > 0) { result = node.Notify(metaData.Results); evaluating = result.Changed; foreach (var item in metaData.Results) { item.FreeReference(); } metaData.Results.Clear(); } if (node.Successors.HasSuccessors) { if (evaluating) { result.IncreaseReferences(node.Successors.Count); foreach (var succ in node.Successors) { if (result != null) { succ.ExecutionMetaData.Results.UnsafeAdd(result); } stack.Push(new Tuple <INotifiable, int>(succ, metaData.TotalVisits)); } } else { foreach (var succ in node.Successors) { stack.Push(new Tuple <INotifiable, int>(succ, metaData.TotalVisits)); } } } metaData.TotalVisits = 0; } }
private void NotifyNode(INotifiable source) { bool evaluating = true; var stack = new Stack <Tuple <INotifiable, int> >(); stack.Push(new Tuple <INotifiable, int>(source, 1)); while (stack.Count > 0) { var tuple = stack.Pop(); var node = tuple.Item1; var metaData = node.ExecutionMetaData; if (metaData.RemainingVisits != tuple.Item2) { int remaining = Interlocked.Add(ref metaData.RemainingVisits, -tuple.Item2); if (remaining > 0) { continue; } } else { metaData.RemainingVisits = 0; } INotificationResult result = null; if (evaluating || metaData.Results.Count > 0) { result = node.Notify(metaData.Results); evaluating = result.Changed; metaData.Results.Clear(); } if (node.Successors.HasSuccessors) { foreach (var succ in node.Successors) { if (result != null && evaluating) { succ.ExecutionMetaData.Results.Add(result); } stack.Push(new Tuple <INotifiable, int>(succ, metaData.TotalVisits)); } } metaData.TotalVisits = 0; } }
private async Task <INotificationResult> Notify(INotificationOptions options) { INotificationResult result = null; return(await Task.Run(() => { if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0)) { return _NotificationManager.Notify(options); } else { ManualResetEvent reset = new ManualResetEvent(false); UIApplication.SharedApplication.InvokeOnMainThread(() => { result = _LocalNotificationManager.Notify(options); reset.Set(); }); reset.WaitOne(); return result; } })); }
public Task <INotificationResult> Notify(INotificationOptions options) { return(Task.Run(() => { ToastNotifier ToastNotifier = ToastNotificationManager.CreateToastNotifier(); Windows.Data.Xml.Dom.XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); Windows.Data.Xml.Dom.XmlNodeList toastNodeList = toastXml.GetElementsByTagName("text"); toastNodeList.Item(0).AppendChild(toastXml.CreateTextNode(options.Title)); toastNodeList.Item(1).AppendChild(toastXml.CreateTextNode(options.Description)); Windows.Data.Xml.Dom.IXmlNode toastNode = toastXml.SelectSingleNode("/toast"); var id = _count.ToString(); var root = toastXml.DocumentElement; root.SetAttribute("launch", id.ToString()); if (!string.IsNullOrEmpty(options.WindowsOptions.LogoUri)) { Windows.Data.Xml.Dom.XmlElement image = toastXml.CreateElement("image"); image.SetAttribute("placement", "appLogoOverride"); var imageUri = options.WindowsOptions.LogoUri; if (!options.WindowsOptions.LogoUri.Contains("//")) { imageUri = $"ms-appx:///{options.WindowsOptions.LogoUri}"; } image.SetAttribute("src", imageUri); toastXml.GetElementsByTagName("binding")[0].AppendChild(image); toastXml.GetElementsByTagName("binding")[0].Attributes[0].InnerText = "ToastGeneric"; } if (options.DelayUntil.HasValue) { ScheduledToastNotification toast = new ScheduledToastNotification(toastXml, options.DelayUntil.Value); ToastNotifier.AddToSchedule(toast); return new NotificationResult() { Action = NotificationAction.NotApplicable }; } else { Windows.UI.Notifications.ToastNotification toast = new Windows.UI.Notifications.ToastNotification(toastXml); toast.Tag = id; _count++; toast.Dismissed += Toast_Dismissed; toast.Activated += Toast_Activated; toast.Failed += Toast_Failed; _notificationOptions.Add(id, options); var waitEvent = new ManualResetEvent(false); _resetEvents.Add(id, waitEvent); ToastNotifier.Show(toast); waitEvent.WaitOne(); INotificationResult result = _eventResult[id]; if (!options.IsClickable && result.Action == NotificationAction.Clicked) // A click is transformed to manual dismiss { result = new NotificationResult() { Action = NotificationAction.Dismissed } } ; if (_resetEvents.ContainsKey(id)) { _resetEvents.Remove(id); } if (_eventResult.ContainsKey(id)) { _eventResult.Remove(id); } if (_notificationOptions.ContainsKey(id)) { _notificationOptions.Remove(id); } return result; } })); }
public Entry(INotificationResult item) { Item = item; }
private void NotifyNode(INotifiable node, bool evaluating, int visits) { while (node != null) { var metaData = node.ExecutionMetaData; if (metaData.RemainingVisits == 0) { return; } if (metaData.RemainingVisits != visits) { int remaining = Interlocked.Add(ref metaData.RemainingVisits, -visits); if (remaining != 0) { return; } } else { metaData.RemainingVisits = 0; } INotificationResult result = null; if (evaluating || metaData.Results.Count > 0) { result = node.Notify(metaData.Results); evaluating = result.Changed; foreach (var item in metaData.Results) { item.FreeReference(); } metaData.Results.Clear(); } visits = metaData.TotalVisits; metaData.RemainingVisits = 0; metaData.TotalVisits = 0; if (node.Successors.HasSuccessors) { if (evaluating) { result.IncreaseReferences(node.Successors.Count); if (node.Successors.Count == 1) { node = node.Successors[0]; node.ExecutionMetaData.Results.Add(result); } else { var childTasks = new Task[node.Successors.Count]; for (int i = 0; i < node.Successors.Count && i < childTasks.Length; i++) { var successor = node.Successors[i]; successor.ExecutionMetaData.Results.Add(result); childTasks[i] = Task.Factory.StartNew(() => NotifyNode(successor, true, visits)); } Task.WaitAll(childTasks); return; } } else { if (node.Successors.Count == 1) { node = node.Successors[0]; } else { var childTasks = new Task[node.Successors.Count]; for (int i = 0; i < node.Successors.Count; i++) { var successor = node.Successors[i]; childTasks[i] = Task.Factory.StartNew(() => NotifyNode(successor, true, visits)); } Task.WaitAll(childTasks); return; } } } } }
public INotificationResult Notify(Activity activity, INotificationOptions options) { INotificationResult notificationResult = null; if (options != null) { var notificationId = 0; var id = ""; lock (_lock) { notificationId = _count; id = _count.ToString(); _count++; } int smallIcon; if (options.AndroidOptions.SmallDrawableIcon.HasValue) { smallIcon = options.AndroidOptions.SmallDrawableIcon.Value; } else if (_androidOptions.SmallIconDrawable.HasValue) { smallIcon = _androidOptions.SmallIconDrawable.Value; } else { smallIcon = Android.Resource.Drawable.IcDialogInfo; // As last resort } if (options.DelayUntil.HasValue) { options.AndroidOptions.SmallDrawableIcon = smallIcon; ScheduleNotification(id, options); return(new NotificationResult() { Action = NotificationAction.NotApplicable, Id = notificationId }); } // Show Notification Right Now var dismissIntent = new Intent(DismissedClickIntent); dismissIntent.PutExtra(NotificationId, notificationId); var pendingDismissIntent = PendingIntent.GetBroadcast(Application.Context, (StartId + notificationId), dismissIntent, 0); var clickIntent = new Intent(OnClickIntent); clickIntent.PutExtra(NotificationId, notificationId); clickIntent.PutExtra(NotificationForceOpenApp, options.AndroidOptions.ForceOpenAppOnNotificationTap); // Add custom args if (options.CustomArgs != null) { foreach (var arg in options.CustomArgs) { clickIntent.PutExtra(arg.Key, arg.Value); } } var pendingClickIntent = PendingIntent.GetBroadcast(Application.Context, (StartId + notificationId), clickIntent, 0); if (!string.IsNullOrEmpty(options.AndroidOptions.HexColor) && options.AndroidOptions.HexColor.Substring(0, 1) != "#") { options.AndroidOptions.HexColor = "#" + options.AndroidOptions.HexColor; } Android.App.Notification.Builder builder = new Android.App.Notification.Builder(Application.Context) .SetContentTitle(options.Title) .SetContentText(options.Description) .SetSmallIcon(smallIcon) // Must have small icon to display .SetPriority((int)NotificationPriority.High) // Must be set to High to get Heads-up notification .SetDefaults(NotificationDefaults.All) // Must also include vibrate to get Heads-up notification .SetAutoCancel(true) // To allow click event to trigger delete Intent .SetContentIntent(pendingClickIntent) // Must have Intent to accept the click .SetDeleteIntent(pendingDismissIntent) .SetColor(Color.ParseColor(options.AndroidOptions.HexColor)); try { // Notification Channel if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O) { var notificationChannelId = GetOrCreateChannel(options.AndroidOptions.ChannelOptions); if (!string.IsNullOrEmpty(notificationChannelId)) { builder.SetChannelId(notificationChannelId); } } } catch { } // System.MissingMethodException: Method 'Android.App.Notification/Builder.SetChannelId' not found. // I know this is bad, but I can't replicate it on any version, and many people are experiencing it. Android.App.Notification notification = builder.Build(); NotificationManager notificationManager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager; notificationManager.Notify(notificationId, notification); if (options.DelayUntil.HasValue) { return(new NotificationResult() { Action = NotificationAction.NotApplicable, Id = notificationId }); } var timer = new Timer(x => TimerFinished(id, options.ClearFromHistory, options.AllowTapInNotificationCenter), null, TimeSpan.FromSeconds(7), TimeSpan.FromMilliseconds(-1)); var resetEvent = new ManualResetEvent(false); ResetEvent.Add(id, resetEvent); resetEvent.WaitOne(); // Wait for a result notificationResult = EventResult[id]; if (!options.IsClickable && notificationResult.Action == NotificationAction.Clicked) { notificationResult.Action = NotificationAction.Dismissed; notificationResult.Id = notificationId; } if (EventResult.ContainsKey(id)) { EventResult.Remove(id); } if (ResetEvent.ContainsKey(id)) { ResetEvent.Remove(id); } // Dispose of Intents and Timer pendingClickIntent.Cancel(); pendingDismissIntent.Cancel(); timer.Dispose(); } return(notificationResult); }