Oda*_*aym 5 android calendar alarmmanager alarms
我在这里包含完整的问题描述,因为我不确定解决方案背后的逻辑是否正确,但我很确定它与我设置警报本身的方式有关,导致这种不准确,或者有时只是纯粹的故障(警报根本不会触发).
用户可以从药物列表中添加新药物.
屏幕1
找到某种药物后,点击它会显示此屏幕http://imgur.com/nLC9gTG
该屏幕包含Medication的名称,在"Posology"标题下(绿色栏)是可以添加该Medication的提醒的地方.
忘记"单位"字段.
"频率"字段接受一个数字,"频率"字段右侧的标签是可点击的,它会显示一个下拉菜单,用户可以从中选择"每日时间"或"每周时间".
"星期几"标签(屏幕截图中的标签为空)也是可点击的,它向用户显示一个下拉菜单,用户可以从一周中选择多天.
"治疗持续时间"字段接受一个数字,"治疗持续时间"字段右侧的标签将反映用户选择的"频率"(如果是"每周一次",那么该标签将说"周",如果是"每月一次"然后该标签将说"几个月").
屏幕2
在第二个屏幕截图中http://imgur.com/AcUmlHH - 有一个开关允许用户启用他试图添加的此药物(项目,实例等)的提醒.
如果上面的"频率"字段的数字大于0(例如2),则提醒开关将创建一个提醒字段列表,它将显示在"获取通知"绿色栏的下方.
当用户最终按下"添加药物"时,将在数据库中创建新的药物对象,以及用户为此药物对象选择添加的"频率"(提醒的数量).
创建一个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
Run Code Online (Sandbox Code Playgroud)
创建MedicationReminder表:
Medication (foreign key for the Medication table)
Calendar
int[] days_of_week
totalTimesToTrigger
Run Code Online (Sandbox Code Playgroud)
在创建此新的Medication对象时:
Medication medication = new Medication();
medication.setFrequency()
medication.setName().setDosage().setRemindersEnabled()....
assignForeignCollectionToParentObject(medication);
Run Code Online (Sandbox Code Playgroud)
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());
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是当添加药物提醒时,它们总是在被添加后不久被触发,并且全部同时被触发.
假设我选择周六和周五的频率2,治疗持续时间为1周.这意味着将添加总共4个提醒,周五为2,周六为2.
当我这样做,它恰好是一个星期六,警报同时在星期六同时触发.
怎么了?
当你这样做时:
medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis());
medReminder.getAlarmTime().set(Calendar.DAY_OF_WEEK, dayChosen);
Run Code Online (Sandbox Code Playgroud)
结果是不可预测的。如果当天是星期一并且您拨打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.
| 归档时间: |
|
| 查看次数: |
387 次 |
| 最近记录: |