public async Task CancelNotification(NotificationOccurrence notificationOccurrence) { // todo removing not matter if actual notification has been cancelled or not await this.storage.DeleteAsync(notificationOccurrence); // cancel alarm var alarmManager = (AlarmManager)this.ctx.GetSystemService(Context.AlarmService); Intent intent = new Intent(this.ctx, typeof(NotificationPublisher)); intent.SetAction("GO_TO_MEDICATION"); if (PendingIntent.GetBroadcast(this.ctx, notificationOccurrence.Id.Value, intent, PendingIntentFlags.CancelCurrent) != null) { System.Diagnostics.Debug.Write($"[PILLER] Cancelling alarm with id {notificationOccurrence.Id.Value}."); PendingIntent alarmIntent = PendingIntent.GetBroadcast(this.ctx, notificationOccurrence.Id.Value, intent, PendingIntentFlags.CancelCurrent); alarmManager.Cancel(alarmIntent); } else { System.Diagnostics.Debug.Write($"[PILLER] Alarm with id {notificationOccurrence.Id.Value} does not exist."); } // cancel notification itself var notificationManager = (NotificationManager)this.ctx.GetSystemService(Context.NotificationService); notificationManager.Cancel(notificationOccurrence.Id.Value); }
private async Task SetAlarm(Notification notification, int id, DateTime occurrenceDate, Intent notificationIntent) { var firingCal = Java.Util.Calendar.Instance; firingCal.Set(CalendarField.Year, occurrenceDate.Year); firingCal.Set(CalendarField.Month, occurrenceDate.Month - 1); firingCal.Set(CalendarField.DayOfMonth, occurrenceDate.Day); firingCal.Set(CalendarField.HourOfDay, occurrenceDate.Hour); firingCal.Set(CalendarField.Minute, occurrenceDate.Minute); firingCal.Set(CalendarField.Second, occurrenceDate.Second); var triggerTime = firingCal.TimeInMillis; // for test purposes only var dateFormat = new SimpleDateFormat("dd:MM:yy:HH:mm:ss"); var cal = dateFormat.Format(triggerTime); var notificationOccurrence = new NotificationOccurrence(id, occurrenceDate, triggerTime); await this.storage.SaveAsync(notificationOccurrence); notificationIntent.PutExtra(NotificationPublisher.NOTIFICATION_ID, notificationOccurrence.Id.Value); notificationIntent.PutExtra(NotificationPublisher.MEDICATION_ID, id); notificationIntent.PutExtra(NotificationPublisher.NOTIFICATION, notification); notificationIntent.PutExtra(NotificationPublisher.NOTIFICATION_FIRE_TIME, triggerTime); var requestId = DateTime.Now.Millisecond; PendingIntent pendingIntent = PendingIntent.GetBroadcast(this.ctx, requestId, notificationIntent, PendingIntentFlags.CancelCurrent); AlarmManager alarmManager = (AlarmManager)this.ctx.GetSystemService(Context.AlarmService); alarmManager.SetExact(AlarmType.RtcWakeup, triggerTime, pendingIntent); }
public async Task DeleteOverdue(NotificationOccurrence notification) { await this.notifications.CancelNotification(notification); await this.storage.DeleteByKeyAsync <NotificationOccurrence>(notification.Id.Value); Mvx.Resolve <IMvxMessenger>().Publish(new DataChangedMessage(this)); }
public async Task OverdueNotification(NotificationOccurrence notificationOccurrence, MedicationDosage medicationDosage) { var notificationIntent = new Intent(this.ctx, typeof(NotificationPublisher)); notificationIntent.SetAction("GO_TO_MEDICATION"); var not = NotificationHelper.GetNotification(this.ctx, medicationDosage, notificationOccurrence, notificationIntent); await this.SetAlarm(medicationDosage.Name, medicationDosage.Dosage, not, notificationOccurrence.Id.Value, notificationOccurrence, notificationIntent); }
public async Task DeleteNearest(NotificationOccurrence notification) { UserDialogs.Instance.ShowLoading(); await this.notifications.CancelNotification(notification); await Init(); UserDialogs.Instance.HideLoading(); //await this.notifications.ScheduleNotification(notification); }
public static async Task AddNotificationOccurrences(MedicationDosage medDosage) { if (medDosage.Days.AllSelected()) { // schedule for every occurrence of hour for every 24 hours foreach (var hour in medDosage.HoursEncoded.Split(';')) { var occurrence = new NotificationOccurrence() { Name = medDosage.Name, Dosage = medDosage.Dosage, MedicationDosageId = medDosage.Id.Value, ThumbnailImage = medDosage.ThumbnailName, OccurrenceDateTime = NextOccurrenceFromHour(TimeSpan.Parse(hour)) }; await storage.SaveAsync(occurrence); } } else { // todo calculate all dates upon selected days of week // NumberOfDaysUntil returns non-negative values so the only thing that you should be careful of // is the nearest day/hour combination which may occur in the past and should be scheduled for week later var todayDay = DateTime.Now.DayOfWeek.ToDaysOfWeek(); // schedule in a weekly manner for each day of week foreach (var hour in medDosage.HoursEncoded.Split(';')) { foreach (var day in medDosage.Days.GetSelected()) { day.TestNumberOfDaysUntil(); var occurrenceDate = DateTime.Now.AddDays(todayDay.NumberOfDaysUntil(day)).Date; var occurrenceTime = TimeSpan.Parse(hour); var occurrenceDateTime = new DateTime(occurrenceDate.Year, occurrenceDate.Month, occurrenceDate.Day, occurrenceTime.Hours, occurrenceTime.Minutes, 0); var occurrence = new NotificationOccurrence() { Name = medDosage.Name, Dosage = medDosage.Dosage, MedicationDosageId = medDosage.Id.Value, ThumbnailImage = medDosage.ThumbnailName, OccurrenceDateTime = occurrenceDateTime }; await storage.SaveAsync(occurrence); } } } }
public async Task ScheduleNotification(NotificationOccurrence notificationOccurrence, MedicationDosage medicationDosage = null) { if (medicationDosage == null) { medicationDosage = await this.storage.GetAsync <MedicationDosage>(notificationOccurrence.MedicationDosageId); } var notificationIntent = new Intent(this.ctx, typeof(NotificationPublisher)); notificationIntent.SetAction("GO_TO_MEDICATION"); var not = NotificationHelper.GetNotification(this.ctx, medicationDosage, notificationOccurrence, notificationIntent); await this.SetAlarm(medicationDosage.Name, medicationDosage.Dosage, not, notificationOccurrence.Id.Value, notificationOccurrence, notificationIntent); }
public override void OnReceive(Context context, Intent intent) { this.Init(context); try { NotificationManager notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService); var notification = intent.GetParcelableExtra(NOTIFICATION) as Notification; var medicationId = intent.GetIntExtra(MEDICATION_ID, 0); // notification itself if (notification != null) { var notificationId = intent.GetIntExtra(NOTIFICATION_ID, 0); var fireTime = intent.GetLongExtra(NOTIFICATION_FIRE_TIME, 0); notificationManager.Notify(notificationId, notification); //var dateFormat = new SimpleDateFormat("dd:MM:yy:HH:mm:ss"); //var cal = dateFormat.Format(fireTime); Task.Run(async() => { var notifications = await this.storage.List <NotificationOccurrence>(n => n.Id == notificationId); var currentNotification = notifications.FirstOrDefault(); var medications = await this.storage.List <MedicationDosage>(n => n.Id == medicationId); var medicationDosage = medications.FirstOrDefault(); //check if current notification is an overdue notification (if it should be sheduled again) var currentTimeSpan = currentNotification.OccurrenceDateTime.TimeOfDay; DateTime newOccurrenceDateTime; if (medicationDosage.DosageHours.Contains(currentTimeSpan)) { if (medicationDosage.Days.AllSelected()) { newOccurrenceDateTime = currentNotification.OccurrenceDateTime.AddDays(1); } else { newOccurrenceDateTime = currentNotification.OccurrenceDateTime.AddDays(7); } var occurrence = new NotificationOccurrence() { Name = currentNotification.Name, Dosage = currentNotification.Dosage, MedicationDosageId = currentNotification.MedicationDosageId, OccurrenceDateTime = newOccurrenceDateTime, ThumbnailImage = currentNotification.ThumbnailImage }; if (currentNotification != null) { await this.notificationService.CancelNotification(currentNotification); await this.storage.DeleteAsync(currentNotification); } else { System.Diagnostics.Debug.Write($"Notification with id {notificationId} could not be found in database."); } await this.storage.SaveAsync(occurrence); await this.notificationService.ScheduleNotification(occurrence, medicationDosage); Mvx.Resolve <IMvxMessenger>().Publish(new NotificationsChangedMessage(this)); } else { if (currentNotification != null) { await this.storage.DeleteAsync(currentNotification); } else { System.Diagnostics.Debug.Write($"Notification with id {notificationId} could not be found in database."); } } // find overdue notifications var nowCalendar = Calendar.Instance; var now = nowCalendar.TimeInMillis; var overdueNotificationsOccurrences = notifications.Where(n => n.OccurrenceDateMillis < now); foreach (var overdueNotificationOccurrence in overdueNotificationsOccurrences) { var medication = await this.storage.GetAsync <MedicationDosage>(overdueNotificationOccurrence.MedicationDosageId); Intent notificationIntent = new Intent(context, typeof(NotificationPublisher)); notificationIntent.PutExtra(NotificationPublisher.MEDICATION_ID, medicationId); var overdueNotification = NotificationHelper.GetNotification(context, medication, overdueNotificationOccurrence, notificationIntent); notificationManager.Notify(overdueNotificationOccurrence.Id.Value, overdueNotification); } }); } else { System.Diagnostics.Debug.WriteLine(intent.Action); System.Diagnostics.Debug.WriteLine(medicationId); var notificationId = intent.GetIntExtra(NOTIFICATION_ID, 0); if (intent.Action == "GO_TO_MEDICATION") { // open medication screen var navigation = new MedicationDosageNavigation(); navigation.MedicationDosageId = medicationId; var bundle = new MvxBundle(); bundle.Write(navigation); var request = new MvxViewModelRequest <MedicationDosageViewModel>(bundle, null, MvxRequestedBy.UserAction); //var request = new MvxViewModelRequest(); //request.ParameterValues = new System.Collections.Generic.Dictionary<string, string>(); //request.ParameterValues.Add("nav", Mvx.Resolve<IMvxJsonConverter>().SerializeObject(navigation)); request.ViewModelType = typeof(MedicationDosageViewModel); var requestTranslator = Mvx.Resolve <IMvxAndroidViewModelRequestTranslator>(); var newActivity = requestTranslator.GetIntentFor(request); newActivity.SetFlags(ActivityFlags.NewTask); context.StartActivity(newActivity); Task.Run(async() => { var notificationToDismiss = await this.storage.GetAsync <NotificationOccurrence>(notificationId); await this.notificationService.CancelNotification(notificationToDismiss); notificationManager.Cancel(notificationId); }); } if (intent.Action == "NOTIFCATION_DISMISS") { // todo remove notification totally or rather reschedule ? // maybe this action should be from settings (user decides in settings what happens if she/he dismisses notification)? var dismissedNotificationId = intent.GetIntExtra(NOTIFICATION_ID, 0); Task.Run(async() => { var dismissedNotification = await this.storage.GetAsync <NotificationOccurrence>(dismissedNotificationId); await this.notificationService.CancelNotification(dismissedNotification); Mvx.Resolve <IMvxMessenger>().Publish(new NotificationsChangedMessage(this)); }); } if (intent.Action == "OK") { Task.Run(async() => { await this.notificationService.CancelAndRemove(notificationId); Mvx.Resolve <IMvxMessenger>().Publish(new NotificationsChangedMessage(this)); }); notificationManager.Cancel(notificationId); } /*if (intent.Action == "NO") * { * var fireTime = intent.GetLongExtra(NOTIFICATION_FIRE_TIME, 0); * var name = intent.GetStringExtra(MEDICATION_NAME); * * Task.Run(async () => * { * var overdueNotification = new OverdueNotification(medicationId, name, fireTime); * await this.storage.SaveAsync(overdueNotification); * }); * * notificationManager.Cancel(notificationId); * }*/ if (intent.Action == "LATER") { Task.Run(async() => { var name = intent.GetStringExtra(MEDICATION_NAME); var fireTime = intent.GetLongExtra(NOTIFICATION_FIRE_TIME, 0); var settingsDataString = Mvx.Resolve <ISettings>().GetValue <string>(SettingsData.Key); var settingsData = JsonConvert.DeserializeObject <SettingsData>(settingsDataString); DateTime occurrenceDate = DateTime.Now.AddMinutes(settingsData.SnoozeMinutes); var medications = await this.storage.List <MedicationDosage>(); var medicationDosage = medications.FirstOrDefault(n => n.Id == medicationId); var newNotification = new NotificationOccurrence(medicationDosage.Name, medicationDosage.Dosage, medicationDosage.Id.Value, occurrenceDate, fireTime + 90000) { ThumbnailImage = medicationDosage.ThumbnailName }; await this.storage.SaveAsync <NotificationOccurrence>(newNotification); await this.notificationService.CancelAndRemove(notificationId); Mvx.Resolve <IMvxMessenger>().Publish(new NotificationsChangedMessage(this)); await notificationService.OverdueNotification(newNotification, medicationDosage); }); notificationManager.Cancel(notificationId); } } } catch (Exception ex) { Console.WriteLine($"[PILLER] Error during alarm receive: {ex}"); } }
public static Notification GetNotification(Context context, MedicationDosage medication, NotificationOccurrence notificationOccurrence, Intent notificationIntent) { var builder = new NotificationCompat.Builder(context); builder.SetContentTitle(medication.Name); builder.SetTicker($"[PILLER] {medication.Name}"); builder.SetSmallIcon(Resource.Drawable.pill64x64); var data = JsonConvert.DeserializeObject <SettingsData>(Mvx.Resolve <ISettings>().GetValue <string>(SettingsData.Key)); Android.Net.Uri ring = Android.Net.Uri.Parse(data.RingUri); builder.SetSound(ring); builder.SetPriority((int)NotificationPriority.High); builder.SetVisibility((int)NotificationVisibility.Public); // visible on locked screen RemoteViews contentView = new RemoteViews(context.PackageName, Resource.Layout.customNotification); contentView.SetTextViewText(Resource.Id.titleTextView, medication.Name + " " + medication.Dosage); contentView.SetTextViewText(Resource.Id.descTextView, FormatOccurrence(notificationOccurrence.OccurrenceDateTime)); //contentView.SetImageViewBitmap(Resource.Id.iconView, BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.pill64x64)); RemoteViews contentBigView = new RemoteViews(context.PackageName, Resource.Layout.customBigNotification); contentBigView.SetTextViewText(Resource.Id.titleTextView, medication.Name + " " + medication.Dosage); contentBigView.SetTextViewText(Resource.Id.descTextView, FormatOccurrence(notificationOccurrence.OccurrenceDateTime)); if (medication?.ThumbnailName == null) { var roundedImage = BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.pill64x64); contentView.SetImageViewBitmap(Resource.Id.imageView, roundedImage); contentBigView.SetImageViewBitmap(Resource.Id.iconView, roundedImage); } else { var imageLoader = Mvx.Resolve <ImageLoaderService>(); byte[] array = imageLoader.LoadImage(medication.ThumbnailName); contentView.SetImageViewBitmap(Resource.Id.imageView, BitmapFactory.DecodeByteArray(array, 0, array.Length)); contentBigView.SetImageViewBitmap(Resource.Id.imageView, BitmapFactory.DecodeByteArray(array, 0, array.Length)); } var medicationId = medication.Id.Value; var notificationId = notificationOccurrence.Id.Value; System.Diagnostics.Debug.Write(notificationId); Intent okIntent = new Intent(notificationIntent); Intent noIntent = new Intent(notificationIntent); Intent laterIntent = new Intent(notificationIntent); notificationIntent.PutExtra(NotificationPublisher.MEDICATION_ID, medicationId); okIntent.PutExtra(NotificationPublisher.MEDICATION_ID, medicationId); noIntent.PutExtra(NotificationPublisher.MEDICATION_ID, medicationId); laterIntent.PutExtra(NotificationPublisher.MEDICATION_ID, medicationId); notificationIntent.PutExtra(NotificationPublisher.NOTIFICATION_ID, notificationId); okIntent.PutExtra(NotificationPublisher.NOTIFICATION_ID, notificationId); noIntent.PutExtra(NotificationPublisher.NOTIFICATION_ID, notificationId); laterIntent.PutExtra(NotificationPublisher.NOTIFICATION_ID, notificationId); okIntent.SetAction("OK"); noIntent.SetAction("LATER"); //laterIntent.SetAction("LATER"); PendingIntent ok_intent = PendingIntent.GetBroadcast(context, Environment.TickCount, okIntent, 0); contentBigView.SetOnClickPendingIntent(Resource.Id.okButton, ok_intent); PendingIntent no_intent = PendingIntent.GetBroadcast(context, Environment.TickCount, noIntent, 0); contentBigView.SetOnClickPendingIntent(Resource.Id.noButton, no_intent); //PendingIntent later_intent = PendingIntent.GetBroadcast(context, Environment.TickCount, laterIntent, 0); //contentBigView.SetOnClickPendingIntent(Resource.Id.laterButton, later_intent); //contentBigView.SetImageViewBitmap(Resource.Id.imageView, BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.pill64x64)); if (medication?.ThumbnailName == null) { contentBigView.SetImageViewBitmap(Resource.Id.imageView, BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.pill64x64)); } else { ImageLoaderService imageLoader = Mvx.Resolve <ImageLoaderService>(); byte[] array = imageLoader.LoadImage(medication.ThumbnailName); contentBigView.SetImageViewBitmap(Resource.Id.imageView, BitmapFactory.DecodeByteArray(array, 0, array.Length)); } builder.SetCustomContentView(contentView); builder.SetCustomBigContentView(contentBigView); var notification = builder.Build(); // action upon notification click var notificationMainAction = new Intent(context, typeof(NotificationPublisher)); notificationMainAction.PutExtra(NotificationPublisher.MEDICATION_ID, medicationId); notificationMainAction.PutExtra(NotificationPublisher.NOTIFICATION_ID, notificationId); notificationMainAction.SetAction("GO_TO_MEDICATION"); var flags = (PendingIntentFlags)((int)PendingIntentFlags.CancelCurrent | (int)NotificationFlags.AutoCancel); notification.ContentIntent = PendingIntent.GetBroadcast(context, notificationId, notificationMainAction, flags); // action upon notification dismiss var notificationDismissAction = new Intent(context, typeof(NotificationPublisher)); notificationDismissAction.PutExtra(NotificationPublisher.MEDICATION_ID, medicationId); notificationDismissAction.PutExtra(NotificationPublisher.NOTIFICATION_ID, notificationId); notificationDismissAction.SetAction("NOTIFCATION_DISMISS"); //var flags = (PendingIntentFlags)((int)PendingIntentFlags.CancelCurrent | (int)NotificationFlags.AutoCancel); notification.DeleteIntent = PendingIntent.GetBroadcast(context, notificationId, notificationDismissAction, flags); return(notification); }