diff --git a/app/src/main/java/com/philliphsu/clock2/OnBootUpAlarmScheduler.java b/app/src/main/java/com/philliphsu/clock2/OnBootUpAlarmScheduler.java index 4fd4a8e..f32bc16 100644 --- a/app/src/main/java/com/philliphsu/clock2/OnBootUpAlarmScheduler.java +++ b/app/src/main/java/com/philliphsu/clock2/OnBootUpAlarmScheduler.java @@ -4,11 +4,10 @@ import android.app.IntentService; import android.content.Context; import android.content.Intent; +import com.philliphsu.clock2.model.AlarmDatabaseHelper.AlarmCursor; import com.philliphsu.clock2.model.DatabaseManager; import com.philliphsu.clock2.util.AlarmUtils; -import java.util.List; - /** * An {@link IntentService} subclass for handling asynchronous task requests in * a service on a separate handler thread. @@ -60,12 +59,15 @@ public class OnBootUpAlarmScheduler extends IntentService { @Override protected void onHandleIntent(Intent intent) { if (intent != null) { - List alarms = DatabaseManager.getInstance(this).getAlarms(); - for (Alarm a : alarms) { - if (a.isEnabled()) { - AlarmUtils.scheduleAlarm(this, a, false); + // IntentService already works in a background thread, so we don't need to use a loader. + AlarmCursor cursor = DatabaseManager.getInstance(this).queryAlarms(); + while (cursor.moveToNext()) { + Alarm alarm = cursor.getAlarm(); + if (alarm.isEnabled()) { + AlarmUtils.scheduleAlarm(this, alarm, false); } } + cursor.close(); /* final String action = intent.getAction(); if (ACTION_FOO.equals(action)) { diff --git a/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java b/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java index 1c84bf5..021333a 100644 --- a/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java @@ -5,6 +5,8 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.support.annotation.StringRes; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; import android.support.v7.app.ActionBar; import android.support.v7.widget.SwitchCompat; import android.text.SpannableString; @@ -28,6 +30,7 @@ import com.philliphsu.clock2.BaseActivity; import com.philliphsu.clock2.DaysOfWeek; import com.philliphsu.clock2.R; import com.philliphsu.clock2.SharedPreferencesHelper; +import com.philliphsu.clock2.model.AlarmLoader; import com.philliphsu.clock2.model.DatabaseManager; import com.philliphsu.clock2.ringtone.RingtoneActivity; import com.philliphsu.clock2.util.AlarmUtils; @@ -51,14 +54,16 @@ import static com.philliphsu.clock2.util.Preconditions.checkNotNull; public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyListener, EditAlarmContract.View, // TODO: Remove @Override from the methods AlarmUtilsHelper, - SharedPreferencesHelper { + SharedPreferencesHelper, + LoaderManager.LoaderCallbacks { private static final String TAG = "EditAlarmActivity"; 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 int REQUEST_PICK_RINGTONE = 0; private static final int ID_MENU_ITEM = 0; - + + private long mOldAlarmId; private Uri mSelectedRingtoneUri; private Alarm mOldAlarm; private DatabaseManager mDatabaseManager; @@ -80,7 +85,17 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi setWeekDaysText(); mNumpad.setKeyListener(this); mDatabaseManager = DatabaseManager.getInstance(this); // MUST be before loading alarm - loadAlarm(getIntent().getLongExtra(EXTRA_ALARM_ID, -1)); + mOldAlarmId = getIntent().getLongExtra(EXTRA_ALARM_ID, -1); + if (mOldAlarmId != -1) { + // getLoaderManager() for support fragments by default returns the + // support version of LoaderManager. However, since this is an Activity, + // we have both the native getLoaderManager() and getSupportLoaderManager(). + // Use the latter to remain consistent with the rest of our current code base. + getSupportLoaderManager().initLoader(0, null, this); + } else { + // Nothing to load, so show default values + showDetails(); + } setTimeTextHint(); // TODO: private access } @@ -503,11 +518,22 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi return AlarmUtils.readPreference(this, key, defaultValue); } - private void loadAlarm(long alarmId) { - mOldAlarm = alarmId > -1 ? mDatabaseManager.getAlarm(alarmId) : null; + @Override + public Loader onCreateLoader(int id, Bundle args) { + return new AlarmLoader(this, mOldAlarmId); + } + + @Override + public void onLoadFinished(Loader loader, Alarm data) { + mOldAlarm = data; showDetails(); } + @Override + public void onLoaderReset(Loader loader) { + // nothing to reset + } + // TODO: Privatize access of each method called here. private void showDetails() { if (mOldAlarm != null) { diff --git a/app/src/main/java/com/philliphsu/clock2/model/AlarmLoader.java b/app/src/main/java/com/philliphsu/clock2/model/AlarmLoader.java new file mode 100644 index 0000000..f321337 --- /dev/null +++ b/app/src/main/java/com/philliphsu/clock2/model/AlarmLoader.java @@ -0,0 +1,23 @@ +package com.philliphsu.clock2.model; + +import android.content.Context; + +import com.philliphsu.clock2.Alarm; + +/** + * Created by Phillip Hsu on 6/30/2016. + */ +public class AlarmLoader extends DataLoader { + + private long mAlarmId; + + public AlarmLoader(Context context, long alarmId) { + super(context); + mAlarmId = alarmId; + } + + @Override + public Alarm loadInBackground() { + return DatabaseManager.getInstance(getContext()).getAlarm(mAlarmId); + } +} diff --git a/app/src/main/java/com/philliphsu/clock2/model/DataLoader.java b/app/src/main/java/com/philliphsu/clock2/model/DataLoader.java new file mode 100644 index 0000000..baaea25 --- /dev/null +++ b/app/src/main/java/com/philliphsu/clock2/model/DataLoader.java @@ -0,0 +1,34 @@ +package com.philliphsu.clock2.model; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; + +/** + * Created by Phillip Hsu on 6/30/2016. + */ +public abstract class DataLoader extends AsyncTaskLoader { + + private D mData; + + public DataLoader(Context context) { + super(context); + } + + @Override + protected void onStartLoading() { + if (mData != null) { + deliverResult(mData); + } else { + forceLoad(); + } + } + + @Override + public void deliverResult(D data) { + mData = data; + if (isStarted()) { + super.deliverResult(data); + } + } + +} diff --git a/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java b/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java index a72cd94..ffe2fc7 100644 --- a/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java +++ b/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java @@ -21,7 +21,6 @@ import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; import static android.app.PendingIntent.FLAG_NO_CREATE; import static android.app.PendingIntent.getActivity; import static com.philliphsu.clock2.util.DateFormatUtils.formatTime; -import static com.philliphsu.clock2.util.Preconditions.checkNotNull; import static java.util.concurrent.TimeUnit.HOURS; /** @@ -75,12 +74,16 @@ public final class AlarmUtils { AlarmManager am = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE); PendingIntent pi = alarmIntent(c, a, true); - am.cancel(pi); - pi.cancel(); + if (pi != null) { + am.cancel(pi); + pi.cancel(); + } pi = notifyUpcomingAlarmIntent(c, a, true); - am.cancel(pi); - pi.cancel(); + if (pi != null) { + am.cancel(pi); + pi.cancel(); + } removeUpcomingAlarmNotification(c, a); @@ -159,9 +162,13 @@ public final class AlarmUtils { .putExtra(RingtoneActivity.EXTRA_ITEM_ID, alarm.id()); int flag = retrievePrevious ? FLAG_NO_CREATE : FLAG_CANCEL_CURRENT; PendingIntent pi = getActivity(context, alarm.intId(), intent, flag); + // Even when we try to retrieve a previous instance that actually did exist, + // null can be returned for some reason. +/* if (retrievePrevious) { checkNotNull(pi); } +*/ return pi; } @@ -176,9 +183,13 @@ public final class AlarmUtils { } int flag = retrievePrevious ? FLAG_NO_CREATE : FLAG_CANCEL_CURRENT; PendingIntent pi = PendingIntent.getBroadcast(context, alarm.intId(), intent, flag); + // Even when we try to retrieve a previous instance that actually did exist, + // null can be returned for some reason. +/* if (retrievePrevious) { checkNotNull(pi); } +*/ return pi; }