Я использую AlarmManager для установки нескольких будильников, которые служат напоминанием в моем приложении.Идея состоит в том, что пользователи будут устанавливать свои собственные сигналы тревоги, которые будут напоминать им об использовании приложения.Однако я столкнулся с проблемой.При изменении системного времени все просроченные сигналы тревоги исчезают сразу (например, если будильник установлен на среду, а дата изменена на четверг, будильник на среду выключится).
Мой сигнал тревогиустановить так:
private static void setWeeklyAlarm(Reminder reminder, Context context, String day) throws ParseException {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, ReminderReceiver.class);
...
intent.putExtra(ALARM_ID, _id);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context,_id, intent, 0);
long alarmTime = 0;
if(DateTimeAssist.getCalendarTimeFromReminder(reminder, day) <= Calendar.getInstance().getTimeInMillis()){
alarmTime = DateTimeAssist.getCalendarTimeFromReminder(reminder, day) + (AlarmManager.INTERVAL_DAY * 7);
} else {
alarmTime = DateTimeAssist.getCalendarTimeFromReminder(reminder, day);
}
alarmManager.setExact(AlarmManager.RTC_WAKEUP, alarmTime,
alarmIntent);
}
Когда сработает будильник, класс ReminderReceiver
отправит уведомление.Затем будильник настроен на повторение на следующей неделе:
public class ReminderReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
...
int _id = intent.getIntExtra(AlarmAssist.ALARM_ID, 0);
AlarmAssist.resetWeeklyAlarm(_id, context);
}
Метод resetWeeklyAlarm
выглядит следующим образом:
public static void resetWeeklyAlarm(int _id, Context context){
Intent repeatIntent = new Intent(context, ReminderReceiver.class);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context,_id,repeatIntent,0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + (AlarmManager.INTERVAL_DAY * 7),
pendingIntent);
}
При изменении системного времени класс ReminderTimeChangeReceiver
называется.Поскольку данные напоминаний хранятся в базе данных Room, удаление и повторное создание напоминаний выполняется в фоновом потоке:
public class ReminderTimeChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
new cancelAndSetAsyncTask().execute(context);
}
private static class cancelAndSetAsyncTask extends AsyncTask<Context, Void, Void> {
@Override
protected Void doInBackground(Context... contexts) {
AppDatabase db = AppDatabase.getDatabase(contexts[0]);
ReminderDao reminderDao = db.reminderDao();
List<Reminder> allReminders = reminderDao.getAllRemindersNotLive();
for(Reminder current : allReminders){
AlarmAssist.deleteReminder(current, contexts[0]);
try {
AlarmAssist.createReminder(current, contexts[0]);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
}
}
Методы deleteReminder
и deleteWeeklyAlarm
являются следующими:
public static void deleteReminder(Reminder reminder, Context context) {
ComponentName receiver = new ComponentName(context, ReminderBootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
List<String> days = ListAssist.convertStringToListOf(reminder.getRepeating());
for(String day : days){
deleteWeeklyAlarm(reminder, context, day);
}
}
public static void deleteWeeklyAlarm(Reminder reminder, Context context, String day){
//Disables the receiver for this alarm
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, ReminderReceiver.class);
final int _id = StringsAssist.concatInts(reminder.getTimeHrs(),
reminder.getTimeMins(), DateTimeAssist.dayToInt(day));
Log.d(TAG, "deleteWeeklyAlarm() called with: reminder = [" + reminder + "], context = [" + context + "], day = [" + day + "]");
Log.d(TAG, "deleteWeeklyAlarm: id" + _id);
PendingIntent deleteIntent = PendingIntent.getBroadcast(context, _id, intent, 0);
alarmManager.cancel(deleteIntent);
deleteIntent.cancel();
}
Я исчерпал много других вопросов здесь, ища ответы, и был вдохновлен на удаление и повторное создание аварий с истекшим сроком действия этим вопросом в частности.Мой вопрос: Почему мои просроченные тревоги все еще срабатывают при изменении системного времени?Может ли быть так, что они активируются до того, как у них есть шанс быть удаленными?Если так, как я мог предотвратить это?
Примечание: Для этого приложения minSdkVersion составляет 22.