我在这里包含完整的问题描述,因为我不确定解决方案背后的逻辑是否正确,但我很确定它与我设置警报的方式有关他们自己导致了这种不准确,或者只是有时是纯粹的错误(警报根本不会触发)。
用户可以从药物清单中添加新的药物。
屏幕1
找到某种药物后,点击它会显示此屏幕http://imgur.com/nLC9gTG
该屏幕包含Medication的名称,并在" Posology"标题(绿色条)是可以添加该药物的提醒的地方。
忘掉"单位"字段。
"频率"字段接受一个数字和标签右边的"频率"字段是可点击的,它会显示一个下拉菜单,用户可以从中选择"时间和#34;或者"每周一次"。
"星期几"标签(屏幕截图中的标签为空)也是可点击的,它向用户显示一个下拉菜单,用户可以从中选择一周中的几天。
治疗持续时间"字段接受一个数字和标签右边的#34;治疗持续时间"字段将反映用户对频率"频率" (如果是""每周时间"那么该标签会说"周",如果它"每个月"那么该标签会说"月")。
屏幕2
在第二个屏幕截图http://imgur.com/AcUmlHH中 - 有一个开关允许用户启用他正在尝试添加的此药物(项目,实例等)的提醒。
如果"频率"上面的字段有一个大于0的数字(例如2),然后提醒开关将创建一个提醒字段列表,它将显示在"获取通知"绿色酒吧。
当用户最终按下"添加药物"时,将在数据库中创建一个新的药物对象,以及"频率" (用户已选择为此Medication对象添加的提醒数量。)
创建一个Medication表:
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
创建MedicationReminder表:
Medication (foreign key for the Medication table)
Calendar
int[] days_of_week
totalTimesToTrigger
创建此新的Medication对象后:
Medication medication = new Medication();
medication.setFrequency()
medication.setName().setDosage().setRemindersEnabled()....
assignForeignCollectionToParentObject(medication);
assignForeignCollectionToParentObject(药物)
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);
}
}
}
}
}
问题是当添加药物提醒时,它们总是在被添加后不久被触发,并且全部同时被触发。
假设我选择星期六和星期五的频率2,治疗时间为1周。这意味着将添加总共4个提醒,周五为2,周六为2。
当我这样做时,恰好是星期六,警报会在星期六同时触发。
出了什么问题?
答案 0 :(得分:3)
执行此操作时:
medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis());
medReminder.getAlarmTime().set(Calendar.DAY_OF_WEEK, dayChosen);
结果无法预测。如果当天是星期一,并且您使用set(Calendar.DAY_OF_WEEK)
致电Calendar.THURSDAY
,那么日期是否应更改为上一个星期四?还是下个星期四?你不知道。
如果您的闹钟立即全部响起,则表示更改DAY_OF_WEEK
会导致日历倒退而不是转发。要在设置DAY_OF_WEEK
后验证,请调用getTimeInMillis()
并将其与当前时间进行比较。如果它更小,那么您的日历已经回溯。要解决此问题,只需在日历中添加7天。
此外,您正在使用此类警报:AlarmManager.ELAPSED_REALTIME_WAKEUP
。此类型采用一个值,表示自设备启动以来经过的时间量。
但是,您使用RTC作为时间值(即:Calendar.getTimeInMillis()
)。这两个值不兼容。如果您想使用RTC,则需要使用AlarmManager.RTC_WAKEUP
。
答案 1 :(得分:2)
问题是当添加药物提醒时,它们总是在被添加后不久被触发,并且全部同时被触发。
那是因为那就是你要求的。您总是在阅读当前时间并将其设置为提醒时间:
medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis());
您从未在this screen中阅读用户提供的时间,即您的提醒的Calendar
字段永远不会设置。这是你的代码:
MedicationReminder medReminder = adapter.getItem(i);
medReminder.setMedication(medicationObject);
medReminder.setDays_of_week(daysOfWeekArray);
for (int aDaysOfWeekArray : daysOfWeekArray) {
if (aDaysOfWeekArray != 0) realDaysSelected++;
}
medReminder.setTotalTimesToTrigger(...);
您错过了实际设置提醒时间的行
答案 2 :(得分:0)
这可能不是你问题的答案,但恕我直言,你应该考虑这个。
我认为这是糟糕的用户体验。此应用程序的用户可能会仅根据时间(没有日期)来混淆提醒的时间。因此,最好在用户能够编辑的每个提醒旁边添加完整日期。当您第一次生成它们时,您可以按正确的顺序设置它们。
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
这也会更好地反映现实世界。让我们考虑一下这个用例:用户有他的手机,但他忘记了用药。他不能在正确的时间接受它,所以他稍后会采取它(甚至可能是tommorow)。这将搞乱计划,但在这种情况下,他可以将日期编辑为他实际服用药物的日期。然后在他编辑的所有提醒之后根据times_per_week,times_per_month调整所有提醒的日期和时间。他不应该把它们改成过去的日期。
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
用户必须仍限于每个提醒的特定日期范围。你不能让他挑选任何约会。这是基于他的计划设置和当前日期,但我不想进入。这需要做很多工作。
如果将这些更改写入数据库,则不应丢失数据。您可以稍后为您的应用程序添加一项功能:报告用户迟到的次数与用户按时服用药物的次数。这对移动应用程序来说是个不错的小功能。