Alarm Ppreferences applied to code

This commit is contained in:
Phillip Hsu 2016-06-07 02:03:05 -07:00
parent 4b8bbcf5f2
commit dca0a258f8
11 changed files with 87 additions and 49 deletions

View File

@ -1,11 +1,11 @@
package com.philliphsu.clock2; package com.philliphsu.clock2;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.util.Log; import android.util.Log;
import com.philliphsu.clock2.util.AlarmUtils;
import java.util.Arrays; import java.util.Arrays;
/** /**
@ -38,16 +38,14 @@ public class DaysOfWeek {
private static Context sAppContext; private static Context sAppContext;
private static DaysOfWeek sInstance; private static DaysOfWeek sInstance;
private static String sLastPreferredFirstDay; private static int sLastPreferredFirstDay;
public static DaysOfWeek getInstance(Context context) { public static DaysOfWeek getInstance(Context context) {
sAppContext = context.getApplicationContext(); sAppContext = context.getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); int preferredFirstDay = AlarmUtils.firstDayOfWeek(context);
// TODO First day of week preference. Entries are the full days' names and values are their respective integers. if (sInstance == null || preferredFirstDay != sLastPreferredFirstDay) {
String preferredFirstDay = prefs.getString("", "0");
if (sInstance == null || !preferredFirstDay.equals(sLastPreferredFirstDay)) {
sLastPreferredFirstDay = preferredFirstDay; sLastPreferredFirstDay = preferredFirstDay;
sInstance = new DaysOfWeek(Integer.parseInt(preferredFirstDay)); sInstance = new DaysOfWeek(preferredFirstDay);
} }
Log.d(TAG, sInstance.toString()); Log.d(TAG, sInstance.toString());
return sInstance; return sInstance;

View File

@ -28,7 +28,7 @@ public abstract class Numpad extends TableLayout {
// Derived classes need to build this themselves via buildBackspace(). // Derived classes need to build this themselves via buildBackspace().
private ImageButton mBackspace; private ImageButton mBackspace;
private ImageButton mCollapse; // TODO: useless? private ImageButton mCollapse;
private int[] mInput; private int[] mInput;
private int mCount = 0; private int mCount = 0;
private KeyListener mKeyListener; private KeyListener mKeyListener;

View File

@ -0,0 +1,11 @@
package com.philliphsu.clock2;
import android.support.annotation.StringRes;
/**
* Created by Phillip Hsu on 6/6/2016.
*/
public interface SharedPreferencesHelper {
/** Suitable for retrieving the value of a ListPreference */
int getInt(@StringRes int key, int defaultValue);
}

View File

@ -1,7 +1,5 @@
package com.philliphsu.clock2.alarms; package com.philliphsu.clock2.alarms;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.SwitchCompat;
import android.text.SpannableString; import android.text.SpannableString;
@ -54,13 +52,8 @@ public class AlarmViewHolder extends BaseViewHolder<Alarm> {
bindSwitch(alarm.isEnabled()); bindSwitch(alarm.isEnabled());
bindCountdown(alarm.isEnabled(), alarm.ringsIn()); bindCountdown(alarm.isEnabled(), alarm.ringsIn());
// TODO: shared prefs int hoursBeforeUpcoming = AlarmUtils.hoursBeforeUpcoming(getContext());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); boolean visible = alarm.isEnabled() && (alarm.ringsWithinHours(hoursBeforeUpcoming) || alarm.isSnoozed());
// how many hours before alarm is considered upcoming
/*int hoursBeforeUpcoming = Integer.parseInt(prefs.getString(
mContext.getString(-1TODO:R.string.key_notify_me_of_upcoming_alarms),
"2"));*/
boolean visible = alarm.isEnabled() && (alarm.ringsWithinHours(2) || alarm.isSnoozed());
String buttonText = alarm.isSnoozed() String buttonText = alarm.isSnoozed()
? getContext().getString(R.string.title_snoozing_until, formatTime(getContext(), alarm.snoozingUntil())) ? getContext().getString(R.string.title_snoozing_until, formatTime(getContext(), alarm.snoozingUntil()))
: getContext().getString(R.string.dismiss_now); : getContext().getString(R.string.dismiss_now);
@ -102,8 +95,6 @@ public class AlarmViewHolder extends BaseViewHolder<Alarm> {
// TODO: Check if alarm has no recurrence, then turn it off. // TODO: Check if alarm has no recurrence, then turn it off.
} }
// TODO: Break onBind() into smaller helper method calls. Then, you can update certain
// pieces of the VH on demand without having to rebind the whole thing.
private void bindTime(Date date) { private void bindTime(Date date) {
String time = DateFormat.getTimeFormat(getContext()).format(date); String time = DateFormat.getTimeFormat(getContext()).format(date);
if (DateFormat.is24HourFormat(getContext())) { if (DateFormat.is24HourFormat(getContext())) {

View File

@ -4,6 +4,7 @@ import android.content.Intent;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.StringRes;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.SwitchCompat;
import android.text.SpannableString; import android.text.SpannableString;
@ -25,6 +26,7 @@ import com.philliphsu.clock2.Alarm;
import com.philliphsu.clock2.BaseActivity; import com.philliphsu.clock2.BaseActivity;
import com.philliphsu.clock2.DaysOfWeek; import com.philliphsu.clock2.DaysOfWeek;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
import com.philliphsu.clock2.SharedPreferencesHelper;
import com.philliphsu.clock2.model.AlarmsRepository; import com.philliphsu.clock2.model.AlarmsRepository;
import com.philliphsu.clock2.util.AlarmUtils; import com.philliphsu.clock2.util.AlarmUtils;
import com.philliphsu.clock2.util.DurationUtils; import com.philliphsu.clock2.util.DurationUtils;
@ -42,10 +44,10 @@ import static android.view.View.VISIBLE;
import static com.philliphsu.clock2.util.KeyboardUtils.hideKeyboard; import static com.philliphsu.clock2.util.KeyboardUtils.hideKeyboard;
import static com.philliphsu.clock2.util.Preconditions.checkNotNull; import static com.philliphsu.clock2.util.Preconditions.checkNotNull;
public class EditAlarmActivity extends BaseActivity implements public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyListener,
EditAlarmContract.View, EditAlarmContract.View,
AlarmUtilsHelper, AlarmUtilsHelper,
AlarmNumpad.KeyListener { SharedPreferencesHelper {
private static final String TAG = "EditAlarmActivity"; private static final String TAG = "EditAlarmActivity";
public static final String EXTRA_ALARM_ID = "com.philliphsu.clock2.editalarm.extra.ALARM_ID"; public static final String EXTRA_ALARM_ID = "com.philliphsu.clock2.editalarm.extra.ALARM_ID";
private static final RelativeSizeSpan AMPM_SIZE_SPAN = new RelativeSizeSpan(0.5f); private static final RelativeSizeSpan AMPM_SIZE_SPAN = new RelativeSizeSpan(0.5f);
@ -72,7 +74,7 @@ public class EditAlarmActivity extends BaseActivity implements
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setWeekDaysText(); setWeekDaysText();
mNumpad.setKeyListener(this); mNumpad.setKeyListener(this);
mPresenter = new EditAlarmPresenter(this, AlarmsRepository.getInstance(this), this); mPresenter = new EditAlarmPresenter(this, AlarmsRepository.getInstance(this), this, this);
mPresenter.loadAlarm(getIntent().getLongExtra(EXTRA_ALARM_ID, -1)); mPresenter.loadAlarm(getIntent().getLongExtra(EXTRA_ALARM_ID, -1));
mPresenter.setTimeTextHint(); mPresenter.setTimeTextHint();
} }
@ -432,4 +434,9 @@ public class EditAlarmActivity extends BaseActivity implements
public void cancelAlarm(Alarm alarm) { public void cancelAlarm(Alarm alarm) {
AlarmUtils.cancelAlarm(this, alarm); AlarmUtils.cancelAlarm(this, alarm);
} }
@Override
public int getInt(@StringRes int key, int defaultValue) {
return AlarmUtils.readPreference(this, key, defaultValue);
}
} }

View File

@ -5,6 +5,8 @@ import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import com.philliphsu.clock2.Alarm; import com.philliphsu.clock2.Alarm;
import com.philliphsu.clock2.R;
import com.philliphsu.clock2.SharedPreferencesHelper;
import com.philliphsu.clock2.model.Repository; import com.philliphsu.clock2.model.Repository;
import java.util.Date; import java.util.Date;
@ -23,14 +25,17 @@ public class EditAlarmPresenter implements EditAlarmContract.Presenter {
@NonNull private final EditAlarmContract.View mView; @NonNull private final EditAlarmContract.View mView;
@NonNull private final Repository<Alarm> mRepository; @NonNull private final Repository<Alarm> mRepository;
@NonNull private final AlarmUtilsHelper mAlarmUtilsHelper; @NonNull private final AlarmUtilsHelper mAlarmUtilsHelper;
@NonNull private final SharedPreferencesHelper mSharedPreferencesHelper;
@Nullable private Alarm mAlarm; @Nullable private Alarm mAlarm;
public EditAlarmPresenter(@NonNull EditAlarmContract.View view, public EditAlarmPresenter(@NonNull EditAlarmContract.View view,
@NonNull Repository<Alarm> repository, @NonNull Repository<Alarm> repository,
@NonNull AlarmUtilsHelper helper) { @NonNull AlarmUtilsHelper helper,
@NonNull SharedPreferencesHelper sharedPreferencesHelper) {
mView = view; mView = view;
mRepository = repository; mRepository = repository;
mAlarmUtilsHelper = helper; mAlarmUtilsHelper = helper;
mSharedPreferencesHelper = sharedPreferencesHelper;
} }
@Override @Override
@ -128,8 +133,8 @@ public class EditAlarmPresenter implements EditAlarmContract.Presenter {
@Override @Override
public void onPrepareOptionsMenu() { public void onPrepareOptionsMenu() {
if (mAlarm != null && mAlarm.isEnabled()) { if (mAlarm != null && mAlarm.isEnabled()) {
// TODO: Read upcoming threshold preference int hoursBeforeUpcoming = mSharedPreferencesHelper.getInt(R.string.key_notify_me_of_upcoming_alarms, 2);
if ((mAlarm.ringsWithinHours(2))) { if ((mAlarm.ringsWithinHours(hoursBeforeUpcoming))) {
mView.showCanDismissNow(); mView.showCanDismissNow();
} else if (mAlarm.isSnoozed()) { } else if (mAlarm.isSnoozed()) {
mView.showSnoozed(new Date(mAlarm.snoozingUntil())); mView.showSnoozed(new Date(mAlarm.snoozingUntil()));

View File

@ -15,8 +15,8 @@ import android.widget.Toast;
import com.philliphsu.clock2.Alarm; import com.philliphsu.clock2.Alarm;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
import com.philliphsu.clock2.util.AlarmUtils;
import com.philliphsu.clock2.model.AlarmsRepository; import com.philliphsu.clock2.model.AlarmsRepository;
import com.philliphsu.clock2.util.AlarmUtils;
import static com.philliphsu.clock2.util.DateFormatUtils.formatTime; import static com.philliphsu.clock2.util.DateFormatUtils.formatTime;
import static com.philliphsu.clock2.util.Preconditions.checkNotNull; import static com.philliphsu.clock2.util.Preconditions.checkNotNull;
@ -132,7 +132,8 @@ public class RingtoneActivity extends AppCompatActivity implements RingtoneServi
} }
private void snooze() { private void snooze() {
mAlarm.snooze(1); // TODO: Read snooze duration from prefs int snoozeMins = AlarmUtils.snoozeDuration(this);
mAlarm.snooze(snoozeMins);
AlarmUtils.scheduleAlarm(this, mAlarm); AlarmUtils.scheduleAlarm(this, mAlarm);
AlarmsRepository.getInstance(this).saveItems(); AlarmsRepository.getInstance(this).saveItems();
// Display toast // Display toast

View File

@ -19,8 +19,8 @@ import android.util.Log;
import com.philliphsu.clock2.Alarm; import com.philliphsu.clock2.Alarm;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
import com.philliphsu.clock2.util.AlarmUtils;
import com.philliphsu.clock2.model.AlarmsRepository; import com.philliphsu.clock2.model.AlarmsRepository;
import com.philliphsu.clock2.util.AlarmUtils;
import static com.philliphsu.clock2.util.DateFormatUtils.formatTime; import static com.philliphsu.clock2.util.DateFormatUtils.formatTime;
import static com.philliphsu.clock2.util.Preconditions.checkNotNull; import static com.philliphsu.clock2.util.Preconditions.checkNotNull;
@ -67,13 +67,6 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
}; };
private final IBinder mBinder = new RingtoneBinder(); private final IBinder mBinder = new RingtoneBinder();
// TODO: Apply the setting for "Silence after" here by using an AlarmManager to
// schedule an alarm in the future to stop this service, and also update the foreground
// notification to say "alarm missed" in the case of Alarms or "timer expired" for Timers.
// If Alarms and Timers will have distinct settings for this, then consider doing this
// operation in the respective subclass of this service.
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
// Although this is a bound service, we override this method because this class is reused for // Although this is a bound service, we override this method because this class is reused for
@ -89,7 +82,7 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
long id = intent.getLongExtra(EXTRA_ITEM_ID, -1); long id = intent.getLongExtra(EXTRA_ITEM_ID, -1);
if (id < 0) throw new IllegalStateException("No item id set"); if (id < 0) throw new IllegalStateException("No item id set");
Alarm alarm = checkNotNull(AlarmsRepository.getInstance(this).getItem(id)); Alarm alarm = checkNotNull(AlarmsRepository.getInstance(this).getItem(id));
alarm.snooze(1); // TODO: read snooze duration in prefs alarm.snooze(AlarmUtils.snoozeDuration(this));
AlarmUtils.scheduleAlarm(this, alarm); AlarmUtils.scheduleAlarm(this, alarm);
} }
stopSelf(startId); stopSelf(startId);
@ -196,13 +189,12 @@ public class RingtoneService extends Service { // TODO: abstract this, make subc
void onServiceFinish(); void onServiceFinish();
} }
// TODO: For Timers, update the foreground notification to say "timer expired". Also,
// if Alarms and Timers will have distinct settings for the minutes to silence after, then consider
// doing this in the respective subclass of this service.
private void scheduleAutoSilence() { private void scheduleAutoSilence() {
// TODO: Read prefs int minutes = AlarmUtils.minutesToSilenceAfter(this);
//SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); mSilenceHandler.postDelayed(mSilenceRunnable, minutes * 60000);
/*int minutes = Integer.parseInt(pref.getString(
getString(R.string.key_silence_after),
"15"));*/
mSilenceHandler.postDelayed(mSilenceRunnable, 20000);
} }
private PendingIntent getPendingIntent(@NonNull String action, Alarm alarm) { private PendingIntent getPendingIntent(@NonNull String action, Alarm alarm) {

View File

@ -4,9 +4,12 @@ import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.preference.PreferenceManager;
import android.support.annotation.StringRes;
import android.util.Log; import android.util.Log;
import com.philliphsu.clock2.Alarm; import com.philliphsu.clock2.Alarm;
import com.philliphsu.clock2.R;
import com.philliphsu.clock2.UpcomingAlarmReceiver; import com.philliphsu.clock2.UpcomingAlarmReceiver;
import com.philliphsu.clock2.ringtone.RingtoneActivity; import com.philliphsu.clock2.ringtone.RingtoneActivity;
import com.philliphsu.clock2.ringtone.RingtoneService; import com.philliphsu.clock2.ringtone.RingtoneService;
@ -42,10 +45,10 @@ public final class AlarmUtils {
// to handle that yourself by using a wakelock, etc.. // to handle that yourself by using a wakelock, etc..
// We use a WAKEUP alarm to send the upcoming alarm notification so it goes off even if the // We use a WAKEUP alarm to send the upcoming alarm notification so it goes off even if the
// device is asleep. Otherwise, it will not go off until the device is turned back on. // device is asleep. Otherwise, it will not go off until the device is turned back on.
// todo: read shared prefs for number of hours to be notified in advance
long ringAt = alarm.isSnoozed() ? alarm.snoozingUntil() : alarm.ringsAt(); long ringAt = alarm.isSnoozed() ? alarm.snoozingUntil() : alarm.ringsAt();
// If snoozed, upcoming note posted immediately. // If snoozed, upcoming note posted immediately.
am.set(AlarmManager.RTC_WAKEUP, ringAt - 2*3600000, notifyUpcomingAlarmIntent(context, alarm, false)); am.set(AlarmManager.RTC_WAKEUP, ringAt - hoursBeforeUpcoming(context) * 3600000,
notifyUpcomingAlarmIntent(context, alarm, false));
am.setExact(AlarmManager.RTC_WAKEUP, ringAt, alarmIntent(context, alarm, false)); am.setExact(AlarmManager.RTC_WAKEUP, ringAt, alarmIntent(context, alarm, false));
} }
@ -74,6 +77,28 @@ public final class AlarmUtils {
c.sendBroadcast(intent); c.sendBroadcast(intent);
} }
public static int snoozeDuration(Context c) {
return readPreference(c, R.string.key_snooze_duration, 10);
}
// TODO: Consider renaming to hoursToNotifyInAdvance()
public static int hoursBeforeUpcoming(Context c) {
return readPreference(c, R.string.key_notify_me_of_upcoming_alarms, 2);
}
public static int minutesToSilenceAfter(Context c) {
return readPreference(c, R.string.key_silence_after, 15);
}
public static int firstDayOfWeek(Context c) {
return readPreference(c, R.string.key_first_day_of_week, 0 /* Sunday */);
}
public static int readPreference(Context c, @StringRes int key, int defaultValue) {
String value = PreferenceManager.getDefaultSharedPreferences(c).getString(c.getString(key), null);
return null == value ? defaultValue : Integer.parseInt(value);
}
private static PendingIntent alarmIntent(Context context, Alarm alarm, boolean retrievePrevious) { private static PendingIntent alarmIntent(Context context, Alarm alarm, boolean retrievePrevious) {
// TODO: Use appropriate subclass instead // TODO: Use appropriate subclass instead
Intent intent = new Intent(context, RingtoneActivity.class) Intent intent = new Intent(context, RingtoneActivity.class)

View File

@ -72,9 +72,17 @@
<string name="saturday">Saturday</string> <string name="saturday">Saturday</string>
<string name="sunday">Sunday</string> <string name="sunday">Sunday</string>
<string name="monday">Monday</string> <string name="monday">Monday</string>
<string-array name="array_first_day_of_week"> <string name="value_saturday">6</string>
<string name="value_sunday">0</string>
<string name="value_monday">1</string>
<string-array name="entries_first_day_of_week">
<item>@string/saturday</item> <item>@string/saturday</item>
<item>@string/sunday</item> <item>@string/sunday</item>
<item>@string/monday</item> <item>@string/monday</item>
</string-array> </string-array>
<string-array name="values_first_day_of_week">
<item>@string/value_saturday</item>
<item>@string/value_sunday</item>
<item>@string/value_monday</item>
</string-array>
</resources> </resources>

View File

@ -51,9 +51,9 @@
android:key="@string/key_first_day_of_week" android:key="@string/key_first_day_of_week"
android:title="@string/title_first_day_of_week" android:title="@string/title_first_day_of_week"
android:dialogTitle="@string/title_first_day_of_week" android:dialogTitle="@string/title_first_day_of_week"
android:entries="@array/array_first_day_of_week" android:entries="@array/entries_first_day_of_week"
android:entryValues="@array/array_first_day_of_week" android:entryValues="@array/values_first_day_of_week"
android:defaultValue="@string/sunday" android:defaultValue="@string/value_sunday"
android:summary="%s"/> android:summary="%s"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/title_category_timers"> <PreferenceCategory android:title="@string/title_category_timers">