/// <summary> /// Schedules a notification to be delivered. /// </summary> /// <param name="notification">The notification to deliver.</param> public PendingNotification ScheduleNotification(IGameNotification notification) { if (!Initialized) { throw new InvalidOperationException("Must call Initialize() first."); } if (notification == null || Platform == null) { return(null); } // If we queue, don't schedule immediately. // Also immediately schedule non-time based deliveries (for iOS) if ((mode & OperatingMode.Queue) != OperatingMode.Queue || notification.DeliveryTime == null) { Platform.ScheduleNotification(notification); } else if (!notification.Id.HasValue) { // Generate an ID for items that don't have one (just so they can be identified later) int id = Math.Abs(DateTime.Now.ToString("yyMMddHHmmssffffff").GetHashCode()); notification.Id = id; } // Register pending notification var result = new PendingNotification(notification); PendingNotifications.Add(result); return(result); }
// Clear foreground notifications and reschedule stuff from a file private void OnForegrounding() { PendingNotifications.Clear(); Platform.OnForeground(); // Deserialize saved items IList <IGameNotification> loaded = Serializer?.Deserialize(Platform); // Foregrounding if ((mode & OperatingMode.ClearOnForegrounding) == OperatingMode.ClearOnForegrounding) { // Clear on foregrounding Platform.CancelAllScheduledNotifications(); // Only reschedule in reschedule mode, and if we loaded any items if (loaded == null || (mode & OperatingMode.RescheduleAfterClearing) != OperatingMode.RescheduleAfterClearing) { return; } // Reschedule notifications from deserialization foreach (IGameNotification savedNotification in loaded) { if (savedNotification.DeliveryTime > DateTime.Now) { PendingNotification pendingNotification = ScheduleNotification(savedNotification); pendingNotification.Reschedule = true; } } } else { // Just create PendingNotification wrappers for all deserialized items. // We're not rescheduling them because they were not cleared if (loaded == null) { return; } foreach (IGameNotification savedNotification in loaded) { if (savedNotification.DeliveryTime > DateTime.Now) { PendingNotifications.Add(new PendingNotification(savedNotification)); } } } }
/// <summary> /// Check pending list for expired notifications, when in queue mode. /// </summary> protected virtual void Update() { if ((mode & OperatingMode.Queue) != OperatingMode.Queue) { return; } // Check each pending notification for expiry, then remove it for (int i = PendingNotifications.Count - 1; i >= 0; --i) { PendingNotification queuedNotification = PendingNotifications[i]; DateTime? time = queuedNotification.Notification.DeliveryTime; if (time != null && time < DateTime.Now) { PendingNotifications.RemoveAt(i); LocalNotificationExpired?.Invoke(queuedNotification); } } }
/// <summary> /// Respond to application foreground/background events. /// </summary> protected void OnApplicationFocus(bool hasFocus) { if (Platform == null || !Initialized) { return; } inForeground = hasFocus; if (hasFocus) { OnForegrounding(); return; } Platform.OnBackground(); // Backgrounding // Queue future dated notifications if ((mode & OperatingMode.Queue) == OperatingMode.Queue) { // Filter out past events for (var i = PendingNotifications.Count - 1; i >= 0; i--) { PendingNotification pendingNotification = PendingNotifications[i]; // Ignore already scheduled ones if (pendingNotification.Notification.Scheduled) { continue; } // If a non-scheduled notification is in the past (or not within our threshold) // just remove it immediately if (pendingNotification.Notification.DeliveryTime != null && pendingNotification.Notification.DeliveryTime - DateTime.Now < MinimumNotificationTime) { PendingNotifications.RemoveAt(i); } } // Sort notifications by delivery time, if no notifications have a badge number set bool noBadgeNumbersSet = PendingNotifications.All(notification => notification.Notification.BadgeNumber == null); if (noBadgeNumbersSet && AutoBadging) { PendingNotifications.Sort((a, b) => { if (!a.Notification.DeliveryTime.HasValue) { return(1); } if (!b.Notification.DeliveryTime.HasValue) { return(-1); } return(a.Notification.DeliveryTime.Value.CompareTo(b.Notification.DeliveryTime.Value)); }); // Set badge numbers incrementally var badgeNum = 1; foreach (PendingNotification pendingNotification in PendingNotifications) { if (pendingNotification.Notification.DeliveryTime.HasValue && !pendingNotification.Notification.Scheduled) { pendingNotification.Notification.BadgeNumber = badgeNum++; } } } for (int i = PendingNotifications.Count - 1; i >= 0; i--) { PendingNotification pendingNotification = PendingNotifications[i]; // Ignore already scheduled ones if (pendingNotification.Notification.Scheduled) { continue; } // Schedule it now Platform.ScheduleNotification(pendingNotification.Notification); } // Clear badge numbers again (for saving) if (noBadgeNumbersSet && AutoBadging) { foreach (PendingNotification pendingNotification in PendingNotifications) { if (pendingNotification.Notification.DeliveryTime.HasValue) { pendingNotification.Notification.BadgeNumber = null; } } } } // Calculate notifications to save var notificationsToSave = new List <PendingNotification>(PendingNotifications.Count); foreach (PendingNotification pendingNotification in PendingNotifications) { // If we're in clear mode, add nothing unless we're in rescheduling mode // Otherwise add everything if ((mode & OperatingMode.ClearOnForegrounding) == OperatingMode.ClearOnForegrounding) { if ((mode & OperatingMode.RescheduleAfterClearing) != OperatingMode.RescheduleAfterClearing) { continue; } // In reschedule mode, add ones that have been scheduled, are marked for // rescheduling, and that have a time if (pendingNotification.Reschedule && pendingNotification.Notification.Scheduled && pendingNotification.Notification.DeliveryTime.HasValue) { notificationsToSave.Add(pendingNotification); } } else { // In non-clear mode, just add all scheduled notifications if (pendingNotification.Notification.Scheduled) { notificationsToSave.Add(pendingNotification); } } } // Save to disk Serializer.Serialize(notificationsToSave); }