5

我在这里包含了完整的问题描述,因为我不确定解决方案背后的逻辑是否正确,但我很确定这与我自己设置警报的方式有关,这会导致这种不准确,或者只是有时纯粹的故障(警报根本不会触发)。


用户可以从药物列表中添加新药物。

屏幕一

当找到某种药物时,点击它会显示这个屏幕http://imgur.com/nLC9gTG

该屏幕包含药物的名称,并且在“Posology”标题(绿色条)下可以添加该药物的提醒。

忘记“单位”字段。

“频率”字段接受一个数字,“频率”字段右侧的标签是可点击的,它会导致出现一个下拉菜单,用户可以从中选择“一天的次数”或“每周的次数”。

“星期几”标签(屏幕截图中的标签为空)也是可点击的,它为用户提供了一个下拉菜单,用户可以从中选择一周中的几天。

“治疗持续时间”字段接受一个数字,“治疗持续时间”字段右侧的标签将反映用户选择的“频率”(如果是“每周次数”,则该标签将显示“周”,如果是“每月次”,那么该标签将显示“月”)。


屏幕 2

在第二个屏幕截图http://imgur.com/AcUmlHH - 有一个开关允许用户为他尝试添加的这种药物(项目、实例等)启用提醒。

如果上面的“频率”字段的数字大于 0(例如 2),那么提醒 Switch 将创建一个提醒字段列表,它将显示在“获取通知”绿色条的下方。

当用户最终按下“添加药物”时,将在数据库中创建一个新的药物对象,以及用户选择为此药物对象添加的“频率”(提醒次数)。


创建一个药物表:

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 条。

当我这样做时,恰好是星期六,警报会在星期六同时触发。

怎么了?

4

3 回答 3

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.

于 2017-01-30T19:07:47.927 回答
2

问题是当添加药物提醒时,它们总是在添加后不久被触发,并且都是同时触发的。

那是因为那是你所要求的。您始终在读取当前时间并将其设置为提醒时间:

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

您永远不会在此屏幕上阅读用户提供的时间,即Calendar您的提醒字段永远不会设置。这是您的代码:

  MedicationReminder medReminder = adapter.getItem(i);
  medReminder.setMedication(medicationObject);
  medReminder.setDays_of_week(daysOfWeekArray);

  for (int aDaysOfWeekArray : daysOfWeekArray) {
    if (aDaysOfWeekArray != 0) realDaysSelected++;
  }

  medReminder.setTotalTimesToTrigger(...);

您错过了实际设置提醒时间的线路

于 2017-01-29T07:05:58.843 回答
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

这也将更好地反映现实世界。让我们考虑这个用例:用户有他的手机,但他忘了吃药。他不能在正确的时间接受它,所以他稍后再接受它(甚至可能是明天)。这会打乱计划,但在这种情况下,他可以将日期编辑为他实际服药的日期。然后,您在他编辑的提醒之后调整所有提醒的日期和时间,以遵循基于 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

对于每个提醒,用户仍必须限制在一定的日期范围内。你不能让他随便挑日期。这是基于他的计划设置和当前日期,但我不想参与其中。这是很多工作。

如果您将这些更改写入数据库,则应该不会丢失数据。您可以稍后在您的应用程序中添加一项功能:报告用户迟到的次数与用户按时服药的次数。这是移动应用程序的一个不错的小功能。

于 2017-02-02T09:21:52.827 回答