/** * ORcycle, Copyright 2014, 2015, PSU Transportation, Technology, and People Lab. * * @author Robin Murray <robin5@pdx.edu> (code) * @author Miguel Figliozzi <figliozzi@pdx.edu> and ORcycle team (general app * design and features, report questionnaires and new ORcycle features) * * For more information on the project, go to * http://www.pdx.edu/transportation-lab/orcycle and http://www.pdx.edu/transportation-lab/app-development * * Updated/modified for Oregon pilot study and app deployment. * * ORcycle is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or any later version. * ORcycle is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with * ORcycle. If not, see <http://www.gnu.org/licenses/>. * */ package edu.pdx.cecs.orcycle; import java.util.Calendar; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.util.Log; public class Reminder { private static final String MODULE_TAG = "Reminder"; public static final String EXTRA_REMINDER_NAME = "REMINDER_NAME"; /** * Value specifying one week in milliseconds * milliseconds/sec * sec/min * min/hr * hr/day * days/week. */ private static final long WEEKLY_INTERVAL = 1000 * 60 * 60 * 24 * 7; /** * Value of the {@code DAY_OF_WEEK} field indicating Sunday. */ private static final int SUNDAY_ID = 0; /** * Value of the {@code DAY_OF_WEEK} field indicating Monday. */ private static final int MONDAY_ID = 1; /** * Value of the {@code DAY_OF_WEEK} field indicating Tuesday. */ private static final int TUESDAY_ID = 2; /** * Value of the {@code DAY_OF_WEEK} field indicating Wednesday. */ private static final int WEDNESDAY_ID = 3; /** * Value of the {@code DAY_OF_WEEK} field indicating Thursday. */ private static final int THURSDAY_ID = 4; /** * Value of the {@code DAY_OF_WEEK} field indicating Friday. */ private static final int FRIDAY_ID = 5; /** * Value of the {@code DAY_OF_WEEK} field indicating Saturday. */ private static final int SATURDAY_ID = 6; private final ReminderHelper rh; private final Context context; public Reminder(Context context, ReminderHelper rh) { this.context = context; this.rh = new ReminderHelper(rh); } public void schedule() { AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); // Cancel all previous alarms for this reminder cancel(context, alarmMgr, rh.getId()); if (rh.getSunday()) schedule(context, rh, alarmMgr, Calendar.SUNDAY ); if (rh.getMonday()) schedule(context, rh, alarmMgr, Calendar.MONDAY ); if (rh.getTuesday()) schedule(context, rh, alarmMgr, Calendar.TUESDAY ); if (rh.getWednesday()) schedule(context, rh, alarmMgr, Calendar.WEDNESDAY ); if (rh.getThursday()) schedule(context, rh, alarmMgr, Calendar.THURSDAY ); if (rh.getFriday()) schedule(context, rh, alarmMgr, Calendar.FRIDAY ); if (rh.getSaturday()) schedule(context, rh, alarmMgr, Calendar.SATURDAY ); } public void cancel() { AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); cancel(context, alarmMgr, rh.getId()); } private static void schedule(Context context, ReminderHelper rh, AlarmManager alarmMgr, int dayOfWeek) { try { long now = System.currentTimeMillis(); // Get a calendar set to now to later use as a time reference Calendar nowCalendar = Calendar.getInstance(); nowCalendar.setTimeInMillis(now); Calendar alarmCalendar = Calendar.getInstance(); alarmCalendar.setTimeInMillis(now); alarmCalendar.set(Calendar.DAY_OF_WEEK, dayOfWeek); alarmCalendar.set(Calendar.HOUR_OF_DAY, rh.getHours()); alarmCalendar.set(Calendar.MINUTE, rh.getMinutes()); alarmCalendar.set(Calendar.SECOND, 0); // When setting the alarm's day of the week value, the calendar may set a day // prior to today. Inorder to stop alarm from firing immediately in this // case, we set the day to fire a week from today if (alarmCalendar.before(nowCalendar)) { alarmCalendar.add(Calendar.DAY_OF_WEEK, 7); // Log.i(MODULE_TAG, alarmCalendar.getTime().toString()); } Log.i(MODULE_TAG, "Alarm set for: " + alarmCalendar.getTime().toString()); PendingIntent alarmIntent = getAlarmIntent(context, dayOfWeek, rh.getId(), rh.getName()); // Set Repeating interval alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, alarmCalendar.getTimeInMillis(), WEEKLY_INTERVAL, alarmIntent); } catch(Exception ex) { Log.e(MODULE_TAG, ex.getMessage()); } } public static void cancel(Context context, long reminderId) { AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); cancel(context, alarmMgr, reminderId); } private static void cancel(Context context, AlarmManager alarmMgr, long reminderId) { cancel(context, alarmMgr, Calendar.SUNDAY, reminderId); cancel(context, alarmMgr, Calendar.MONDAY, reminderId); cancel(context, alarmMgr, Calendar.TUESDAY, reminderId); cancel(context, alarmMgr, Calendar.WEDNESDAY, reminderId); cancel(context, alarmMgr, Calendar.THURSDAY, reminderId); cancel(context, alarmMgr, Calendar.FRIDAY, reminderId); cancel(context, alarmMgr, Calendar.SATURDAY, reminderId); } private static void cancel(Context context, AlarmManager alarmMgr, int dayOfWeek, long reminderId) { try { PendingIntent alarmIntent = getAlarmIntent(context, dayOfWeek, reminderId); alarmMgr.cancel(alarmIntent); } catch(Exception ex) { Log.e(MODULE_TAG, ex.getMessage()); } } private static int getAlarmId(int dayOfWeek, long reminderId) throws Exception { int alarmId = 7 * (int) reminderId; if (alarmId <= 0) { throw new Exception("Invalid reminder ID encountered: " + dayOfWeek); } switch(dayOfWeek) { case Calendar.SUNDAY: alarmId += SUNDAY_ID; break; case Calendar.MONDAY: alarmId += MONDAY_ID; break; case Calendar.TUESDAY: alarmId += TUESDAY_ID; break; case Calendar.WEDNESDAY: alarmId += WEDNESDAY_ID; break; case Calendar.THURSDAY: alarmId += THURSDAY_ID; break; case Calendar.FRIDAY: alarmId += FRIDAY_ID; break; case Calendar.SATURDAY: alarmId += SATURDAY_ID; break; default: throw new Exception("Invalid dayOfWeek encountered: " + dayOfWeek); } return alarmId; } private static PendingIntent getAlarmIntent(Context context, int dayOfWeek, long reminderId) throws Exception { return getAlarmIntent(context, dayOfWeek, reminderId, null); } private static PendingIntent getAlarmIntent(Context context, int dayOfWeek, long reminderId, String name) throws Exception { PendingIntent alarmIntent; String ALARM_ACTION = ReminderReceiver.ACTION_REMIND_USER; Intent intent = new Intent(ALARM_ACTION); if (null != name) { intent.putExtra(EXTRA_REMINDER_NAME, name); } // Construct the pending intent for broadcasting the alarm alarmIntent = PendingIntent.getBroadcast(context, getAlarmId(dayOfWeek, reminderId), intent, PendingIntent.FLAG_CANCEL_CURRENT); return alarmIntent; } }