public async Task ScheduleNotification(MedicationDosage medicationDosage) { Intent notificationIntent = new Intent(this.ctx, typeof(NotificationPublisher)); var notificationDefaults = NotificationDefaults.Lights | NotificationDefaults.Sound | NotificationDefaults.Vibrate; // cancel previously scheduled notifications await this.CancelNotification(medicationDosage.Id.Value); if (medicationDosage.Days.AllSelected()) { // schedule for every occurrence of hour for every 24 hours foreach (var hour in medicationDosage.HoursEncoded.Split(';')) { var nextOccurrenceDate = this.NextOccurrenceFromHour(TimeSpan.Parse(hour)); var not = NotificationHelper.GetNotification(this.ctx, medicationDosage, nextOccurrenceDate, notificationIntent); not.Defaults |= notificationDefaults; // todo get from settings or medication itself (if set custom in medication, otherwise global value from settings) await this.SetAlarm(not, medicationDosage.Id.Value, nextOccurrenceDate, notificationIntent); } } else { // schedule in a weekly manner for each day of week foreach (var hour in medicationDosage.HoursEncoded.Split(';')) { foreach (var day in medicationDosage.Days.GetSelected()) { var nextOccurrenceDate = this.NextOccurrenceFromHourAndDayOfWeek(day, TimeSpan.Parse(hour)); var not = NotificationHelper.GetNotification(this.ctx, medicationDosage, nextOccurrenceDate, notificationIntent); not.Defaults |= notificationDefaults; // todo get from settings or medication itself (if set custom in medication, otherwise global value from settings) await this.SetAlarm(not, medicationDosage.Id.Value, nextOccurrenceDate, notificationIntent); } } } }
public async void Init(MedicationDosageNavigation nav) { if (nav.MedicationDosageId != MedicationDosageNavigation.NewRecord) { isNew = false; MedicationDosage item = await storage.GetAsync <Data.MedicationDosage>(nav.MedicationDosageId); Id = item.Id; MedicationName = item.Name; StartDate = item.From; EndDate = item.To; MedicationDosage = item.Dosage; Monday = item.Days.HasFlag(DaysOfWeek.Monday); Tuesday = item.Days.HasFlag(DaysOfWeek.Tuesday); Wednesday = item.Days.HasFlag(DaysOfWeek.Wednesday); Thursday = item.Days.HasFlag(DaysOfWeek.Thursday); Friday = item.Days.HasFlag(DaysOfWeek.Friday); Saturday = item.Days.HasFlag(DaysOfWeek.Saturday); Sunday = item.Days.HasFlag(DaysOfWeek.Sunday); DosageHours = new List <TimeSpan>(item.DosageHours); HoursLabel = item.Hours; RingUri = item.RingUri; if (!string.IsNullOrEmpty(item.ImageName)) { Bytes = imageLoader.LoadImage(item.ImageName); } } else { isNew = true; selectAllDays(); } loadSettings(); }
public static Notification GetNotification(Context context, MedicationDosage medication, DateTime occurrenceDate, Intent notificationIntent) { var builder = new NotificationCompat.Builder(context); builder.SetContentTitle(medication.Name); builder.SetTicker($"[PILLER] {medication.Name}"); builder.SetSmallIcon(Resource.Drawable.pill64x64); builder.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Alarm)); 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); contentView.SetTextViewText(Resource.Id.descTextView, medication.Dosage + " - " + FormatOccurrence(occurrenceDate)); if (medication?.ThumbnailName == null) { contentView.SetImageViewBitmap(Resource.Id.imageView, BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.pill64x64)); } else { ImageLoaderService imageLoader = Mvx.Resolve <ImageLoaderService>(); byte[] array = imageLoader.LoadImage(medication.ThumbnailName); contentView.SetImageViewBitmap(Resource.Id.imageView, BitmapFactory.DecodeByteArray(array, 0, array.Length)); } RemoteViews contentBigView = new RemoteViews(context.PackageName, Resource.Layout.customBigNotification); contentBigView.SetTextViewText(Resource.Id.titleTextView, medication.Name); contentBigView.SetTextViewText(Resource.Id.descTextView, medication.Dosage + " - " + FormatOccurrence(occurrenceDate)); PendingIntent intent = PendingIntent.GetActivity(context, 0, notificationIntent, 0); contentBigView.SetOnClickPendingIntent(Resource.Id.okButton, intent); intent = PendingIntent.GetActivity(context, 0, notificationIntent, 0); contentBigView.SetOnClickPendingIntent(Resource.Id.noButton, intent); intent = PendingIntent.GetActivity(context, 0, notificationIntent, 0); contentBigView.SetOnClickPendingIntent(Resource.Id.laterButton, intent); 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); return(builder.Build()); }
public async Task CancelAllNotificationsForMedication(MedicationDosage medicationDosage) { var notifications = await this.storage.List <NotificationOccurrence>(o => o.MedicationDosageId == medicationDosage.Id.Value); foreach (var notification in notifications) { await this.CancelNotification(notification); } }
public async Task ScheduleNotifications(MedicationDosage medicationDosage) { // NotificationOccurrence table already contains nearest occurrences, just loop over them to shcedule var notificationOccurrences = await this.storage.List <NotificationOccurrence>(o => o.MedicationDosageId == medicationDosage.Id.Value); foreach (var notificationOccurrence in notificationOccurrences) { await this.ScheduleNotification(notificationOccurrence, medicationDosage); } }
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 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 MedicationDosageViewModel() { this.DosageHours = new RxUI.ReactiveList <TimeSpan>(); var canSave = this.WhenAny( vm => vm.MedicationName, vm => vm.MedicationDosage, vm => vm.Monday, vm => vm.Tuesday, vm => vm.Wednesday, vm => vm.Thursday, vm => vm.Friday, vm => vm.Saturday, vm => vm.Sunday, vm => vm.DosageHours.Count, (n, d, m, t, w, th, f, sa, su, h) => !String.IsNullOrWhiteSpace(n.Value) && !String.IsNullOrWhiteSpace(d.Value) && (m.Value | t.Value | w.Value | th.Value | f.Value | sa.Value | su.Value) && h.Value > 0); this.TakePhotoCommand = ReactiveCommand.CreateFromTask(() => PictureChooser.TakePicture(100, 90)); this.TakePhotoCommand.Subscribe(x => { if (x != null) { this.OnPicture(x); } }); this.Save = RxUI.ReactiveCommand.CreateFromTask <Unit, bool>(async _ => { var dataRecord = new MedicationDosage { Id = this.Id, Name = this.MedicationName, Dosage = this.MedicationDosage, Days = (this.Monday ? DaysOfWeek.Monday : DaysOfWeek.None) | (this.Tuesday ? DaysOfWeek.Tuesday : DaysOfWeek.None) | (this.Wednesday ? DaysOfWeek.Wednesday : DaysOfWeek.None) | (this.Thursday ? DaysOfWeek.Thursday : DaysOfWeek.None) | (this.Friday ? DaysOfWeek.Friday : DaysOfWeek.None) | (this.Saturday ? DaysOfWeek.Saturday : DaysOfWeek.None) | (this.Sunday ? DaysOfWeek.Sunday : DaysOfWeek.None), DosageHours = this.DosageHours }; if (this.Bytes != null) { dataRecord.ImageName = $"image_{medicationName}"; dataRecord.ThumbnailName = $"thumbnail_{medicationName}"; imageLoader.SaveImage(this.Bytes, dataRecord.ImageName); imageLoader.SaveImage(this.Bytes, dataRecord.ThumbnailName, 30); } await this.storage.SaveAsync <MedicationDosage>(dataRecord); //var notification = new CoreNotification(dataRecord.Id.Value, dataRecord.Name, "Rano i wieczorem", new RepeatPattern() { DayOfWeek = dataRecord.Days, Interval = RepetitionInterval.None, RepetitionFrequency = 1 }); await this.notifications.ScheduleNotification(dataRecord); return(true); }, canSave); var canDelete = this.WhenAny(x => x.Id, id => id.Value.HasValue); this.Delete = RxUI.ReactiveCommand.CreateFromTask <Data.MedicationDosage, bool>(async _ => { if (this.Id.HasValue) { await this.storage.DeleteByKeyAsync <MedicationDosage>(this.Id.Value); return(true); } return(false); }, canDelete); this.SelectAllDays = ReactiveCommand <Unit, Unit> .Create(() => { Monday = true; Tuesday = true; Wednesday = true; Thursday = true; Friday = true; Saturday = true; Sunday = true; }); //save sie udal, albo nie - tu dosatniemy rezultat komendy. Jak sie udal, to zamykamy ViewModel this.Save .Subscribe(result => { if (result) { Mvx.Resolve <IMvxMessenger>().Publish(new DataChangedMessage(this)); this.Close(this); } }); this.Save.ThrownExceptions.Subscribe(ex => { UserDialogs.Instance.ShowError(AppResources.MedicationDosageView_SaveError); // show nice message to the user }); this.Delete .Subscribe(result => { if (result) { Mvx.Resolve <IMvxMessenger>().Publish(new DataChangedMessage(this)); this.Close(this); } }); }
public MedicationDosageViewModel() { ShowDialog = ReactiveCommand.Create(() => this.ShowViewModel <BottomDialogViewModel>()); this.DosageHours = new List <TimeSpan>(); var canSave = this.WhenAny( vm => vm.MedicationName, vm => vm.MedicationDosage, vm => vm.Monday, vm => vm.Tuesday, vm => vm.Wednesday, vm => vm.Thursday, vm => vm.Friday, vm => vm.Saturday, vm => vm.Sunday, vm => vm.DosageHours, (n, d, m, t, w, th, f, sa, su, hours) => !String.IsNullOrWhiteSpace(n.Value) && !String.IsNullOrWhiteSpace(d.Value) && (m.Value | t.Value | w.Value | th.Value | f.Value | sa.Value | su.Value) && hours.Value.Count > 0); this.TakePhotoCommand = ReactiveCommand.CreateFromTask(() => PictureChooser.TakePicture(1920, 75)); this.TakePhotoCommand .Where(x => x != null) .Select(x => this.OnPicture(x)) .Subscribe(); this.Save = RxUI.ReactiveCommand.CreateFromTask <Unit, bool>(async _ => { var dataRecord = new MedicationDosage { Id = this.Id, Name = this.MedicationName, From = this.StartDate, To = this.EndDate, Dosage = this.MedicationDosage, Days = (this.Monday ? DaysOfWeek.Monday : DaysOfWeek.None) | (this.Tuesday ? DaysOfWeek.Tuesday : DaysOfWeek.None) | (this.Wednesday ? DaysOfWeek.Wednesday : DaysOfWeek.None) | (this.Thursday ? DaysOfWeek.Thursday : DaysOfWeek.None) | (this.Friday ? DaysOfWeek.Friday : DaysOfWeek.None) | (this.Saturday ? DaysOfWeek.Saturday : DaysOfWeek.None) | (this.Sunday ? DaysOfWeek.Sunday : DaysOfWeek.None), DosageHours = this.DosageHours, Hours = this.HoursLabel, RingUri = this.RingUri }; if (!string.IsNullOrEmpty(this.StartDate) && !string.IsNullOrEmpty(this.EndDate)) { DateTime start = DateTime.Parse(this.StartDate); DateTime end = DateTime.Parse(this.EndDate); if (start > end) { UserDialogs.Instance.Toast("Ustaw prawidłowo zakres dat."); return(false); } } if (this.Bytes != null) { dataRecord.ImageName = $"image_{medicationName}"; dataRecord.ThumbnailName = $"thumbnail_{medicationName}"; imageLoader.SaveImage(this.Bytes, dataRecord.ImageName); imageLoader.SaveImage(this.Bytes, dataRecord.ThumbnailName, 120); } await this.storage.SaveAsync <MedicationDosage>(dataRecord); // usuwam poprzednie notyfikacje await this.notifications.CancelAllNotificationsForMedication(dataRecord); // dodaję najbliższe wystąpienia do tabeli NotificationOccurrence await DbHelper.AddNotificationOccurrences(dataRecord); // dodaję notyfikacje - w środku czytam NotificationOccurrence await this.notifications.ScheduleNotifications(dataRecord); Mvx.Resolve <IMvxMessenger>().Publish(new NotificationsChangedMessage(this)); return(true); }, canSave); var canDelete = this.WhenAny(x => x.Id, id => id.Value.HasValue); this.Delete = RxUI.ReactiveCommand.CreateFromTask <Data.MedicationDosage, bool>(async _ => { if (this.Id.HasValue) { await this.storage.DeleteByKeyAsync <MedicationDosage>(this.Id.Value); await this.notifications.CancelAndRemove(this.Id.Value); return(true); } return(false); }, canDelete); this.SelectAllDays = ReactiveCommand.Create(() => { selectAllDays(); }); //save sie udal, albo nie - tu dosatniemy rezultat komendy. Jak sie udal, to zamykamy ViewModel this.Save .Subscribe(result => { if (result) { Mvx.Resolve <IMvxMessenger>().Publish(new DataChangedMessage(this)); this.Close(this); } }); this.Save.ThrownExceptions.Subscribe(ex => { UserDialogs.Instance.ShowError(AppResources.MedicationDosageView_SaveError); // show nice message to the user }); this.Delete .Subscribe(result => { if (result) { Mvx.Resolve <IMvxMessenger>().Publish(new DataChangedMessage(this)); this.Close(this); } }); GoSettings = ReactiveCommand.Create(() => this.ShowViewModel <SettingsViewModel>()); this.WhenAnyValue(x => x.TimeItems) .Where(x => x != null) .Select(ti => ti.ItemChanged) .Switch() .Subscribe(_ => { CheckedHours = this.TimeItems.Where(x => x.Checked).ToList(); setHours(); }); //Observe days and Humaziner this.WhenAnyValue(x => x.Monday, x => x.Tuesday, x => x.Wednesday, x => x.Thursday, x => x.Friday, x => x.Saturday, x => x.Sunday) .Subscribe(days => DaysLabel = HumanizeOrdinationScheme(new[] { days.Item1, days.Item2, days.Item3, days.Item4, days.Item5, days.Item6, days.Item7 })); }
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); }