Selecting ringtone works

This commit is contained in:
Phillip Hsu 2016-06-02 14:09:09 -07:00
parent 2f5eff6842
commit 680fd28782
4 changed files with 80 additions and 16 deletions

View File

@ -11,7 +11,8 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTask">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>

View File

@ -77,7 +77,7 @@ public abstract class Alarm implements JsonSerializable {
// Fields that were not set when build() is called will throw an exception. // Fields that were not set when build() is called will throw an exception.
// TODO: How can QualityMatters get away with not setting defaults????? // TODO: How can QualityMatters get away with not setting defaults?????
return new AutoValue_Alarm.Builder() return new AutoValue_Alarm.Builder()
//.id(-1) // Set when build() is called .id(-1)
.hour(0) .hour(0)
.minutes(0) .minutes(0)
.recurringDays(new boolean[DaysOfWeek.NUM_DAYS]) .recurringDays(new boolean[DaysOfWeek.NUM_DAYS])
@ -192,16 +192,16 @@ public abstract class Alarm implements JsonSerializable {
@AutoValue.Builder @AutoValue.Builder
public abstract static class 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. // 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 // 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. // class after copying and pasting the accessor fields here.
public abstract Builder id(long id); public abstract Builder id(long id);
public abstract Builder hour(int hour); public abstract Builder hour(int hour);
public abstract Builder minutes(int minutes); public abstract Builder minutes(int minutes);
/* // TODO: If using an immutable collection instead, can use its Builder instance // TODO: If using an immutable collection instead, can use its Builder instance
// and provide an "accumulating" method // and provide an "accumulating" method
abstract boolean[] recurringDays(); /*abstract boolean[] recurringDays();
public final Builder setRecurring(int day, boolean recurs) { public final Builder setRecurring(int day, boolean recurs) {
checkDay(day) checkDay(day)
recurringDays()[day] = recurs; recurringDays()[day] = recurs;
@ -209,6 +209,12 @@ public abstract class Alarm implements JsonSerializable {
} }
*/ */
public abstract Builder recurringDays(boolean[] recurringDays); 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 label(String label);
public abstract Builder ringtone(String ringtone); public abstract Builder ringtone(String ringtone);
public abstract Builder vibrates(boolean vibrates); public abstract Builder vibrates(boolean vibrates);

View File

@ -1,6 +1,6 @@
package com.philliphsu.clock2.editalarm; package com.philliphsu.clock2.editalarm;
import android.media.Ringtone; 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;
@ -26,14 +26,18 @@ import butterknife.Bind;
import butterknife.OnClick; import butterknife.OnClick;
import static android.text.format.DateFormat.getTimeFormat; 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.SATURDAY;
import static com.philliphsu.clock2.DaysOfWeek.SUNDAY; import static com.philliphsu.clock2.DaysOfWeek.SUNDAY;
public class EditAlarmActivity extends BaseActivity { public class EditAlarmActivity extends BaseActivity {
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 int REQUEST_PICK_RINGTONE = 0;
private static final int ID_MENU_ITEM = 0; private static final int ID_MENU_ITEM = 0;
@Nullable private Alarm mAlarm; @Nullable private Alarm mAlarm;
private Uri mSelectedRingtoneUri;
@Bind(R.id.save) Button mSave; @Bind(R.id.save) Button mSave;
@Bind(R.id.delete) Button mDelete; @Bind(R.id.delete) Button mDelete;
@ -62,8 +66,7 @@ public class EditAlarmActivity extends BaseActivity {
mDays[at].setChecked(mAlarm.isRecurring(i)); mDays[at].setChecked(mAlarm.isRecurring(i));
} }
mLabel.setText(mAlarm.label()); mLabel.setText(mAlarm.label());
Ringtone r = RingtoneManager.getRingtone(this, Uri.parse(mAlarm.ringtone())); mSelectedRingtoneUri = Uri.parse(mAlarm.ringtone());
mRingtone.setText(r.getTitle(this));
mVibrate.setChecked(mAlarm.vibrates()); mVibrate.setChecked(mAlarm.vibrates());
if (mAlarm.isSnoozed()) { if (mAlarm.isSnoozed()) {
String title = getString(R.string.title_snoozing_until, String title = getString(R.string.title_snoozing_until,
@ -73,8 +76,19 @@ public class EditAlarmActivity extends BaseActivity {
ab.setDisplayShowTitleEnabled(true); ab.setDisplayShowTitleEnabled(true);
ab.setTitle(title); 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 @Override
@ -94,6 +108,16 @@ public class EditAlarmActivity extends BaseActivity {
return super.onPrepareOptionsMenu(menu); 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 @Override
protected int layoutResId() { protected int layoutResId() {
return R.layout.activity_edit_alarm; return R.layout.activity_edit_alarm;
@ -104,16 +128,45 @@ public class EditAlarmActivity extends BaseActivity {
return 0; 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) @OnClick(R.id.save)
void save() { void save() {
boolean[] days = new boolean[7]; boolean[] days = new boolean[NUM_DAYS];
days[0] = true; for (int i = SUNDAY; i <= SATURDAY; i++) {
days[1] = true; // What position in the week is this day located at?
days[6] = true; 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() 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(); .build();
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); AlarmsRepository.getInstance(this).addItem(a);
}
finish(); 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 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));
}
} }

View File

@ -23,7 +23,7 @@ public abstract class BaseRepository<T extends JsonSerializable> implements Repo
// the intention is that we hold onto the global context so this // the intention is that we hold onto the global context so this
// never gets GCed for the lifetime of the app. // never gets GCed for the lifetime of the app.
@NonNull private final Context mContext; @NonNull private final Context mContext;
@NonNull private final List<T> mItems; @NonNull private final List<T> mItems; // TODO: Consider ArrayMap<Long, T>?
@NonNull private final JsonIoHelper<T> mIoHelper; @NonNull private final JsonIoHelper<T> mIoHelper;
// TODO: Test that the callbacks work. // TODO: Test that the callbacks work.