public static void ScheduleDayBeforeAlarm(Context context, AccountDataItem account, DateTime today, AgendaViewItemsGroup agendaItems) { if (agendaItems == null) { return; } DateTime dayBeforeReminderTime = RemindersExtension.GetDayBeforeReminderTime(today, account, agendaItems); DateTime timeToScheduleAt; // If we haven't reached that time yet for "due tomorrow" if (dayBeforeReminderTime > DateTime.Now) { timeToScheduleAt = dayBeforeReminderTime.AddMilliseconds(1); } // Otherwise we'll need to set the timer for the "due today" else { timeToScheduleAt = today.AddDays(1).AddMilliseconds(1); } AlarmManagerHelper.Schedule( context: context, receiverType: typeof(UpdateDayBeforeNotificationReceiver), wakeTime: timeToScheduleAt, uriData: "powerplanner:?localAccountId=" + account.LocalAccountId, wakeDevice: true); }
private async System.Threading.Tasks.Task InitializeDataAsync() { List <object> items = null; _now = DateTime.Now; bool hasAccount = false; bool hasSemester = false; List <ViewItemSchedule> schedulesToday = new List <ViewItemSchedule>(); try { await System.Threading.Tasks.Task.Run(async delegate { var account = await AccountsManager.GetLastLogin(); if (account != null) { _localAccountId = account.LocalAccountId; hasAccount = true; const int DAYS_INCLUDING_TODAY = 7; var scheduleTileData = await ScheduleTileDataHelper.LoadAsync(account, _now.Date, DAYS_INCLUDING_TODAY); if (scheduleTileData.HasSemester) { hasSemester = true; items = new List <object>(); foreach (var dayData in scheduleTileData.GetDataForAllDays()) { if (dayData.Holidays.Any()) { // If we already displayed these holidays, skip subsequent duplicate days if (items.Count >= dayData.Holidays.Length && items.TakeLast(dayData.Holidays.Length).SequenceEqual(dayData.Holidays)) { // Skip } else { // If not today if (!dayData.IsToday) { // We add the date header only for non-today items.Add(dayData.Date); } items.AddRange(dayData.Holidays); } } else if (dayData.Schedules.Any()) { // If not today if (!dayData.IsToday) { // If there's currently no items if (items.Count == 0) { // Add the text saying no class today! items.Add(PowerPlannerResources.GetString("String_NoClassToday")); } // We add the date header only for non-today items.Add(dayData.Date); } // If today if (dayData.IsToday) { foreach (var s in dayData.Schedules) { if (s.EndTime.TimeOfDay > _now.TimeOfDay) { items.Add(s); schedulesToday.Add(s); } } if (items.Count == 0) { items.Add(PowerPlannerResources.GetString("String_NoMoreClasses")); } } else { items.AddRange(dayData.Schedules); } } } } } }); if (items == null || items.Count == 0) { if (hasSemester) { items = new List <object>() { PowerPlannerResources.GetString("String_NoClassesThisWeek") }; } else if (hasAccount) { items = new List <object>() { PowerPlannerResources.GetString("String_NoSemester") }; } else { items = new List <object>() { PowerPlannerResources.GetString("String_NoAccount") }; } } _items = items; } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } // Schedule next try { DateTime nextChangeTime = _now.Date.AddDays(1); if (schedulesToday.Count > 0) { nextChangeTime = _now.Date.Add(schedulesToday.First().EndTime.TimeOfDay); } AlarmManagerHelper.Schedule( context: _context, receiverType: typeof(UpdateWidgetScheduleReceiver), wakeTime: nextChangeTime); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }
private static async Task UpdateAndScheduleDayOfNotifications(AccountDataItem account, AgendaViewItemsGroup agendaItems, Context context, NotificationManager notificationManager, DateTime now, bool fromForeground) { string tagForAccountStartsWith = account.LocalAccountId.ToString(); List <StatusBarNotification> existingNotifs; if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.M) { existingNotifs = notificationManager.GetActiveNotifications().Where(i => i.Id == NotificationIds.DAY_OF_NOTIFICATIONS && i.Tag != null && i.Tag.StartsWith(tagForAccountStartsWith)).ToList(); } else { // GetActiveNotifications didn't exist before version 23 existingNotifs = new List <StatusBarNotification>(); } // If no current semester, or no items, then just clear if (agendaItems == null || agendaItems.Items.Count == 0) { foreach (var notif in existingNotifs) { notificationManager.Cancel(notif.Tag, NotificationIds.DAY_OF_NOTIFICATIONS); } return; } DateTime nextReminderTime; var itemsThatCouldHaveNotifs = GetItemsThatCouldHaveDayOfNotifications(account, agendaItems, now, out nextReminderTime); // Remove ones that don't exist anymore for (int i = 0; i < existingNotifs.Count; i++) { var existing = existingNotifs[i]; Guid identifier; if (TryGetItemIdFromDayOfTag(existing.Tag, out identifier)) { if (!itemsThatCouldHaveNotifs.Any(x => x.Item1.Identifier == identifier)) { notificationManager.Cancel(existing.Tag, NotificationIds.DAY_OF_NOTIFICATIONS); existingNotifs.RemoveAt(i); i--; } } } foreach (var item in itemsThatCouldHaveNotifs) { UpdateDayOfNotification(account.LocalAccountId, item.Item1, item.Item2, context, notificationManager, existingNotifs, fromForeground); } // Need to mark them as sent Guid[] newlySentHomeworkReminders = itemsThatCouldHaveNotifs.Select(i => i.Item1).OfType <ViewItemHomework>().Where(i => !i.HasSentReminder).Select(i => i.Identifier).ToArray(); Guid[] newlySentExamReminders = itemsThatCouldHaveNotifs.Select(i => i.Item1).OfType <ViewItemExam>().Where(i => !i.HasSentReminder).Select(i => i.Identifier).ToArray(); if (newlySentHomeworkReminders.Length > 0 || newlySentExamReminders.Length > 0) { var dataStore = await AccountDataStore.Get(account.LocalAccountId); if (dataStore != null) { await dataStore.MarkAndroidRemindersSent(newlySentHomeworkReminders, newlySentExamReminders); } } // Schedule the next alarm if (nextReminderTime > now) { AlarmManagerHelper.Schedule( context: context, receiverType: typeof(UpdateDayOfNotificationsReceiver), wakeTime: nextReminderTime, uriData: "powerplanner:?localAccountId=" + account.LocalAccountId, wakeDevice: true); } }
private async System.Threading.Tasks.Task InitializeDataAsync() { List <object> items = null; List <BaseViewItemHomeworkExam> tasks = null; _now = DateTime.Now; bool hasAccount = false; bool isDisabledInSettings = false; bool hasSemester = false; try { await System.Threading.Tasks.Task.Run(async delegate { var account = await AccountsManager.GetLastLogin(); AccountDataStore data = null; if (account != null) { data = await AccountDataStore.Get(account.LocalAccountId); } if (data != null) { hasAccount = true; isDisabledInSettings = account.MainTileSettings.IsDisabled(); if (!isDisabledInSettings) { _localAccountId = account.LocalAccountId; var currSemesterId = account.CurrentSemesterId; if (currSemesterId != Guid.Empty) { ScheduleViewItemsGroup scheduleViewGroup; try { scheduleViewGroup = await ScheduleViewItemsGroup.LoadAsync(account.LocalAccountId, account.CurrentSemesterId, trackChanges: true, includeWeightCategories: false); } catch { // If semester not found scheduleViewGroup = null; } if (scheduleViewGroup != null) { DateTime dateToStartDisplayingFrom = DateTime.SpecifyKind(account.MainTileSettings.GetDateToStartDisplayingOn(_now.Date), DateTimeKind.Utc); // We don't track changes since we need a fresh version that has been filtered right now. // Otherwise when we update for an event expiring, if we have a cached version, that event wouldn't have expired! var agendaViewGroup = await AgendaViewItemsGroup.LoadAsync(account.LocalAccountId, scheduleViewGroup.Semester, _now.Date, trackChanges: false); hasSemester = true; // We lock the outside, since we are allowing trackChanges on the view items groups (so we have a chance of loading a cached one)... and since we're on a background thread, the lists inside the // view items groups could change while we're enumerating, hence throwing an exception. So we lock it to ensure this won't happen, and then we return a copy of the items that we need. using (await agendaViewGroup.DataChangeLock.LockForReadAsync()) { var filtered = agendaViewGroup.Items .Where(i => i.Date.Date >= dateToStartDisplayingFrom); if (!account.MainTileSettings.ShowHomework) { filtered = filtered.Where(i => !(i is ViewItemHomework)); } if (!account.MainTileSettings.ShowExams) { filtered = filtered.Where(i => !(i is ViewItemExam)); } // Agenda view group doesn't sort, so we have to sort it tasks = filtered .OrderBy(i => i) .Take(20) .ToList(); // Add date headers items = new List <object>(); DateTime lastHeader = DateTime.MinValue; foreach (var t in tasks) { if (lastHeader != t.Date.Date) { items.Add(t.Date.Date); lastHeader = t.Date.Date; } items.Add(t); } } } } } } }); if (items == null || items.Count == 0) { if (hasSemester) { items = new List <object>() { PowerPlannerResources.GetString("String_NothingDue") }; } else if (isDisabledInSettings) { items = new List <object>() { PowerPlannerResources.GetString("String_WidgetDisabled") }; } else if (hasAccount) { items = new List <object>() { PowerPlannerResources.GetString("String_NoSemester") }; } else { items = new List <object>() { PowerPlannerResources.GetString("String_NoAccount") }; } } _items = items; } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } // Schedule next try { if (tasks != null && tasks.Count > 0) { DateTime?nextChangeTime = GetNextAgendaChangeTime(tasks, _now); if (nextChangeTime != null) { AlarmManagerHelper.Schedule( context: _context, receiverType: typeof(UpdateWidgetAgendaReceiver), wakeTime: nextChangeTime.Value); } } } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }