Adding multiple reminders makes them start at the same time.

I include a full description of the problem here because I’m not quite sure that the logic of the solution is even correct, but I’m sure that it is related to the way I set the alarms themselves, which causes inaccuracies or just a clean error (alarms do not work).


The user can add a new medicine from the list of drugs.

Screen 1

When a specific medicine is discovered, clicking on it will show this screen http://imgur.com/nLC9gTG

This screen also contains the name of the medicine and under the heading "Posology" (green bar), where you can add reminders that the medicine can be added.

Forget the "Units" field.

The "Frequency" field takes a number, and the label to the right of the "Frequency" field is clickable, this leads to the appearance of a drop-down menu from which the user can select "once a day" or "once a week" ".

The label "Days of the week" (the label is empty in the screenshot) is also available for clicks, it presents the user with a drop-down menu from which the user can select several days from the days of the week.

The "Duration of treatment" field takes a number, and the label to the right of the "Duration of treatment" field will display the user-defined option "Frequency" (if it is "once a week", then this label will indicate "weeks", if it is "once a month", then this label will indicate "months").


Screen 2

In this second screenshot, http://imgur.com/AcUmlHH - there is a switch that allows the user to include reminders for this medicine (item, instance, etc.) that he is trying to add.

If the "Frequency" field above has a number greater than 0 (2, for example), then the Switch reminder will create a list of reminder fields that will be displayed directly below the green "Receive notifications" bar.

When the user finally clicks “Add Medication”, a new Medication object will be created in the database along with the “Frequency” (number of reminders) that the user has decided to add for this Medication object.


Create a drug table:

id name description dosage frequency frequencyType treatmentDuration ForeignCollection<MedicationReminder> ArrayList<DayChoice> (DayChoice is a class with "Day Name" and "Selected") when whenString units unitForm remarks remindersEnabled 

Create the MedicationReminder table:

 Medication (foreign key for the Medication table) Calendar int[] days_of_week totalTimesToTrigger 

By creating this new Medication object:

 Medication medication = new Medication(); medication.setFrequency() medication.setName().setDosage().setRemindersEnabled().... assignForeignCollectionToParentObject(medication); 

assignForeignCollectionToParentObject (medicines)

 private void assignForeignCollectionToParentObject(Medication medicationObject) { medicationDAO.assignEmptyForeignCollection(medicationObject, "medicationReminders"); MedicationRemindersRecyclerAdapter adapter = (MedicationRemindersRecyclerAdapter) remindersRecyclerView.getAdapter(); //Clear previous reminders medicationObject.getMedicationReminders().clear(); for (int i = 0; i < adapter.getItemCount(); i++) { int realDaysSelected = 0; MedicationReminder medReminder = adapter.getItem(i); medReminder.setMedication(medicationObject); medReminder.setDays_of_week(daysOfWeekArray); //These days are populated when the user selected them from the "Days of Week" clickable label for (int aDaysOfWeekArray : daysOfWeekArray) { if (aDaysOfWeekArray != 0) realDaysSelected++; } medReminder.setTotalTimesToTrigger( Integer.parseInt(treatmentDurationET.getText().toString()) * realDaysSelected); medicationObject.getMedicationReminders().add(medReminder); } setupMedicationReminders(medicationObject.getMedicationReminders().iterator()); } 

setupMedicationReminders ()

 public void setupMedicationReminders(Iterator<MedicationReminder> medicationRemindersIterator) { PendingIntent pendingIntent; AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); while (medicationRemindersIterator.hasNext()) { MedicationReminder medReminder = medicationRemindersIterator.next(); for (int i = 0; i < medReminder.getDays_of_week().length; i++) { int dayChosen = medReminder.getDays_of_week()[i]; if (dayChosen != 0) { medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis()); medReminder.getAlarmTime().set(Calendar.DAY_OF_WEEK, dayChosen); Intent intent = new Intent(AddExistingMedicationActivity.this, AlarmReceiver.class); intent.putExtra(Constants.EXTRAS_ALARM_TYPE, "medications"); intent.putExtra(Constants.EXTRAS_MEDICATION_REMINDER_ITEM, (Parcelable) medReminder); pendingIntent = PendingIntent.getBroadcast(this, medReminder.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT); int ALARM_TYPE = AlarmManager.ELAPSED_REALTIME_WAKEUP; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { am.setExactAndAllowWhileIdle(ALARM_TYPE, medReminder.getAlarmTime().getTimeInMillis(), pendingIntent); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { am.setExact(ALARM_TYPE, medReminder.getAlarmTime().getTimeInMillis(), pendingIntent); } else { am.set(ALARM_TYPE, medReminder.getAlarmTime().getTimeInMillis(), pendingIntent); } } } } } 

The problem is that drug reminders are added, they always start shortly after the addition and all at the same time.

Let's say I choose frequency 2 for Saturday and Friday with a treatment duration of 1 week. This means that a total of 4 reminders will be added, 2 on Friday and 2 on Saturday.

When I do this, and it happens, Saturday, the alarms are triggered simultaneously on Saturday.

What's wrong?

+6
source share
3 answers

When you do this:

 medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis()); medReminder.getAlarmTime().set(Calendar.DAY_OF_WEEK, dayChosen); 

The results are unpredictable. If the current day is Monday, and you call set(Calendar.DAY_OF_WEEK) from Calendar.THURSDAY if the date is changed to the previous Thursday? or next thursday? You do not know.

If your alarms all go away immediately, this will mean that changing DAY_OF_WEEK causes the calendar to go backward, not forward. To make sure that after setting DAY_OF_WEEK call getTimeInMillis() and compare it with the current time. If it is smaller, your calendar will return on time. To fix this, simply add 7 days to the calendar.


In addition, you use this type of alarm: AlarmManager.ELAPSED_REALTIME_WAKEUP . This type takes a value that represents the amount of time that has passed since the device was booted.

However, you use RTC for the time value (for example: Calendar.getTimeInMillis() ). These 2 values ​​are incompatible. If you want to use RTC, you need to use AlarmManager.RTC_WAKEUP .

+3
source

The problem is that drug reminders are added, they always start shortly after the addition and all at the same time.

This is because you requested. You always read the current time and set it to the reminder time:

 medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis()); 

You never read the time provided by the user on this screen , that is, the Calendar field of your reminder is never set. Here is your code:

  MedicationReminder medReminder = adapter.getItem(i); medReminder.setMedication(medicationObject); medReminder.setDays_of_week(daysOfWeekArray); for (int aDaysOfWeekArray : daysOfWeekArray) { if (aDaysOfWeekArray != 0) realDaysSelected++; } medReminder.setTotalTimesToTrigger(...); 

You skipped the line to actually set the reminder time.

+2
source

This may not be the answer to your question, but IMHO you should consider this.

I would say that it is a bad UX. The user of this application could be confused with reminder times based only on time ( without dates ). Therefore, it might be better to add a full date next to each reminder that the user will be able to edit. When you create them for the first time, you install them in the correct order.

 Reminder 1: 2/2/2017 13:04 Reminder 2: 9/2/2017 13:04 Reminder 3: 16/2/2017 13:04 Reminder 4: 25/2/2017 13:04 

It will also reflect the real world better. Let's look at this use case: the user has a phone with him, but he forgot the medicine. He cannot take it at the right time, so he takes it after a while (maybe even tommorow). This will ruin the plan, but in this case, he can edit the date to the date when he actually took the medicine. Then you set the date and time for all reminders after it has been edited to keep track of intervals based on times_per_week, times_per_month. He will not be able to change them to the last date.

 Reminder 1: 2/2/2017 13:04 // He took medication on time Reminder 2: 9/2/2017 13:04 // He missed this one and changed to date bellow 10/2/2017 12:22 // This is when he actually took the medication Reminder 3: 16/2/2017 13:04 // This is no longer valid 17/2/2017 12:22 // You adjust reminder to this date and time Reminder 4: 25/2/2017 13:04 // This is no longer valid 26/2/2017 12:22 // You adjust reminder to this date and time 

The user should still be limited to a specific date range for each reminder. You cannot let him choose any date. This is based on his plan settings and current date, but I do not want to delve into it. This is a lot of work.

If you write these changes to your database, there should be no data loss. Later, you can add a function to your application: a report on how many times the user was late and how many times the user took the medicine on time. This is a nice little feature for a mobile application.

0
source

Source: https://habr.com/ru/post/1014323/


All Articles