From 680fd28782b40af028bfa1cfc7f325eee64d8302 Mon Sep 17 00:00:00 2001 From: Phillip Hsu Date: Thu, 2 Jun 2016 14:09:09 -0700 Subject: [PATCH] Selecting ringtone works --- app/src/main/AndroidManifest.xml | 3 +- .../java/com/philliphsu/clock2/Alarm.java | 16 ++-- .../clock2/editalarm/EditAlarmActivity.java | 75 ++++++++++++++++--- .../clock2/model/BaseRepository.java | 2 +- 4 files changed, 80 insertions(+), 16 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e09d9db..4338caa 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,7 +11,8 @@ + android:theme="@style/AppTheme.NoActionBar" + android:launchMode="singleTask"> diff --git a/app/src/main/java/com/philliphsu/clock2/Alarm.java b/app/src/main/java/com/philliphsu/clock2/Alarm.java index c70b99e..851ba29 100644 --- a/app/src/main/java/com/philliphsu/clock2/Alarm.java +++ b/app/src/main/java/com/philliphsu/clock2/Alarm.java @@ -77,7 +77,7 @@ public abstract class Alarm implements JsonSerializable { // Fields that were not set when build() is called will throw an exception. // TODO: How can QualityMatters get away with not setting defaults????? return new AutoValue_Alarm.Builder() - //.id(-1) // Set when build() is called + .id(-1) .hour(0) .minutes(0) .recurringDays(new boolean[DaysOfWeek.NUM_DAYS]) @@ -192,16 +192,16 @@ public abstract class Alarm implements JsonSerializable { @AutoValue.Builder public abstract static class Builder { - private static long idCount = 0; + private static long idCount = 0; // TODO: change to AtomicLong? // Builder is mutable, so these are inherently setter methods. // By omitting the set- prefix, we reduce the number of changes required to define the Builder // class after copying and pasting the accessor fields here. public abstract Builder id(long id); public abstract Builder hour(int hour); public abstract Builder minutes(int minutes); - /* // TODO: If using an immutable collection instead, can use its Builder instance - // and provide an "accumulating" method - abstract boolean[] recurringDays(); + // TODO: If using an immutable collection instead, can use its Builder instance + // and provide an "accumulating" method + /*abstract boolean[] recurringDays(); public final Builder setRecurring(int day, boolean recurs) { checkDay(day) recurringDays()[day] = recurs; @@ -209,6 +209,12 @@ public abstract class Alarm implements JsonSerializable { } */ public abstract Builder recurringDays(boolean[] recurringDays); + /* + public final Builder recurringDay(boolean[] recurringDays) { + this.recurringDays = Arrays.copyOf(recurringDays, NUM_DAYS); + return this; + } + */ public abstract Builder label(String label); public abstract Builder ringtone(String ringtone); public abstract Builder vibrates(boolean vibrates); 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 a96a1de..9b5d6e8 100644 --- a/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java @@ -1,6 +1,6 @@ package com.philliphsu.clock2.editalarm; -import android.media.Ringtone; +import android.content.Intent; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; @@ -26,14 +26,18 @@ import butterknife.Bind; import butterknife.OnClick; import static android.text.format.DateFormat.getTimeFormat; +import static com.philliphsu.clock2.DaysOfWeek.NUM_DAYS; import static com.philliphsu.clock2.DaysOfWeek.SATURDAY; import static com.philliphsu.clock2.DaysOfWeek.SUNDAY; public class EditAlarmActivity extends BaseActivity { public static final String EXTRA_ALARM_ID = "com.philliphsu.clock2.editalarm.extra.ALARM_ID"; + private static final int REQUEST_PICK_RINGTONE = 0; private static final int ID_MENU_ITEM = 0; + @Nullable private Alarm mAlarm; + private Uri mSelectedRingtoneUri; @Bind(R.id.save) Button mSave; @Bind(R.id.delete) Button mDelete; @@ -62,8 +66,7 @@ public class EditAlarmActivity extends BaseActivity { mDays[at].setChecked(mAlarm.isRecurring(i)); } mLabel.setText(mAlarm.label()); - Ringtone r = RingtoneManager.getRingtone(this, Uri.parse(mAlarm.ringtone())); - mRingtone.setText(r.getTitle(this)); + mSelectedRingtoneUri = Uri.parse(mAlarm.ringtone()); mVibrate.setChecked(mAlarm.vibrates()); if (mAlarm.isSnoozed()) { String title = getString(R.string.title_snoozing_until, @@ -73,8 +76,19 @@ public class EditAlarmActivity extends BaseActivity { ab.setDisplayShowTitleEnabled(true); ab.setTitle(title); } + } else { + // TODO default values } + } else { + // Initializing to Settings.System.DEFAULT_ALARM_ALERT_URI will show + // "Default ringtone (Name)" on the button text, and won't show the + // selection on the dialog when first opened. (unless you choose to show + // the default item in the intent extra?) + // Compare with getDefaultUri(int), which returns the symbolic URI instead of the + // actual sound URI. For TYPE_ALARM, this actually returns the same constant. + mSelectedRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); } + updateRingtoneButtonText(); } @Override @@ -94,6 +108,16 @@ public class EditAlarmActivity extends BaseActivity { return super.onPrepareOptionsMenu(menu); } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // Since this Activity doesn't host fragments, not necessary? + //super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_PICK_RINGTONE && resultCode == RESULT_OK) { + mSelectedRingtoneUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); + updateRingtoneButtonText(); + } + } + @Override protected int layoutResId() { return R.layout.activity_edit_alarm; @@ -104,16 +128,45 @@ public class EditAlarmActivity extends BaseActivity { return 0; } + @OnClick(R.id.ringtone) + void ringtone() { + Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM) + .putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false) + // The ringtone to show as selected when the dialog is opened + .putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, mSelectedRingtoneUri) + // Whether to show "Default" item in the list + .putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false); // TODO: false? + // The ringtone that plays when default option is selected + //.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, DEFAULT_TONE); + startActivityForResult(intent, REQUEST_PICK_RINGTONE); + } + @OnClick(R.id.save) void save() { - boolean[] days = new boolean[7]; - days[0] = true; - days[1] = true; - days[6] = true; + boolean[] days = new boolean[NUM_DAYS]; + for (int i = SUNDAY; i <= SATURDAY; i++) { + // What position in the week is this day located at? + int pos = DaysOfWeek.getInstance(this).positionOf(i); + // Set the state of this day according to its corresponding button + days[i] = mDays[pos].isChecked(); + } Alarm a = Alarm.builder() - .recurringDays(days) + // TODO: set hour and minute + .ringtone(mSelectedRingtoneUri.toString()) + .recurringDays(days) // TODO: See https://github.com/google/auto/blob/master/value/userguide/howto.md#mutable_property + .label(mLabel.getText().toString()) + .vibrates(mVibrate.isChecked()) .build(); - AlarmsRepository.getInstance(this).addItem(a); + a.setEnabled(mSwitch.isChecked()); + if (mAlarm != null) { + // TODO: Cancel any alarm scheduled with the old alarm's ID + // TODO: Schedule the new alarm + AlarmsRepository.getInstance(this).updateItem(mAlarm, a); + } else { + // TODO: Schedule the new alarm + AlarmsRepository.getInstance(this).addItem(a); + } finish(); } @@ -134,4 +187,8 @@ public class EditAlarmActivity extends BaseActivity { mDays[i].setChecked(mDays[i].isChecked()); // force update the text, otherwise it won't be shown } } + + private void updateRingtoneButtonText() { + mRingtone.setText(RingtoneManager.getRingtone(this, mSelectedRingtoneUri).getTitle(this)); + } } diff --git a/app/src/main/java/com/philliphsu/clock2/model/BaseRepository.java b/app/src/main/java/com/philliphsu/clock2/model/BaseRepository.java index 324f98a..183f2f3 100644 --- a/app/src/main/java/com/philliphsu/clock2/model/BaseRepository.java +++ b/app/src/main/java/com/philliphsu/clock2/model/BaseRepository.java @@ -23,7 +23,7 @@ public abstract class BaseRepository implements Repo // the intention is that we hold onto the global context so this // never gets GCed for the lifetime of the app. @NonNull private final Context mContext; - @NonNull private final List mItems; + @NonNull private final List mItems; // TODO: Consider ArrayMap? @NonNull private final JsonIoHelper mIoHelper; // TODO: Test that the callbacks work.