diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a8d8d08..4ff4f20 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,13 +4,14 @@ + + android:theme="@style/AppTheme.Dark">

+ * An alternative to the system's ringtone picker dialog. The differences are: + * (1) this dialog matches the current theme, + * (2) the selected ringtone URI is delivered via the {@link OnRingtoneSelectedListener + * OnRingtoneSelectedListener} callback. */ public class RingtonePickerDialog extends BaseAlertDialogFragment { + private static final String TAG = "RingtonePickerDialog"; - private OnRingtoneSetListener mOnRingtoneSetListener; - private Uri mInitialRingtoneUri; + private RingtoneManager mRingtoneManager; + private OnRingtoneSelectedListener mOnRingtoneSelectedListener; + private Uri mRingtoneUri; + private Ringtone mRingtone; - public interface OnRingtoneSetListener { - void onRingtoneSet(Uri ringtoneUri); + public interface OnRingtoneSelectedListener { + void onRingtoneSelected(Uri ringtoneUri); } /** - * @param initialRingtoneUri the URI of the ringtone to show as initially selected + * @param ringtoneUri the URI of the ringtone to show as initially selected */ - public static RingtonePickerDialog newInstance(OnRingtoneSetListener l, Uri initialRingtoneUri) { + public static RingtonePickerDialog newInstance(OnRingtoneSelectedListener l, Uri ringtoneUri) { RingtonePickerDialog dialog = new RingtonePickerDialog(); - dialog.mOnRingtoneSetListener = l; - dialog.mInitialRingtoneUri = initialRingtoneUri; + dialog.mOnRingtoneSelectedListener = l; + dialog.mRingtoneUri = ringtoneUri; return dialog; } @Override - protected void onOk() { - + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mRingtoneManager = new RingtoneManager(getActivity()); + mRingtoneManager.setType(RingtoneManager.TYPE_ALARM); } - public void setOnRingtoneSetListener(OnRingtoneSetListener onRingtoneSetListener) { - mOnRingtoneSetListener = onRingtoneSetListener; + @Override + protected AlertDialog createFrom(AlertDialog.Builder builder) { + // TODO: We set the READ_EXTERNAL_STORAGE permission. Verify that this includes the user's + // custom ringtone files. + Cursor cursor = mRingtoneManager.getCursor(); + int checkedItem = mRingtoneManager.getRingtonePosition(mRingtoneUri); + String labelColumn = cursor.getColumnName(RingtoneManager.TITLE_COLUMN_INDEX); + + builder.setTitle(R.string.ringtones) + .setSingleChoiceItems(cursor, checkedItem, labelColumn, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Here, 'which' param refers to the position of the item clicked. + mRingtoneUri = mRingtoneManager.getRingtoneUri(which); + mRingtone = mRingtoneManager.getRingtone(which); + // TODO: Deprecated, but setAudioAttributes() is for 21+, so what is the + // pre-21 alternative? + mRingtone.setStreamType(AudioManager.STREAM_ALARM); + mRingtone.play(); + } + }); + return super.createFrom(builder); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + if (mRingtone != null && mRingtone.isPlaying()) { + mRingtone.stop(); + } + } + + @Override + protected void onOk() { + if (mOnRingtoneSelectedListener != null) { + // Here, 'which' param refers to the position of the item clicked. + mOnRingtoneSelectedListener.onRingtoneSelected(mRingtoneUri); + } + dismiss(); + } + + public void setOnRingtoneSelectedListener(OnRingtoneSelectedListener onRingtoneSelectedListener) { + mOnRingtoneSelectedListener = onRingtoneSelectedListener; } } diff --git a/app/src/main/java/com/philliphsu/clock2/alarms/BaseAlarmViewHolder.java b/app/src/main/java/com/philliphsu/clock2/alarms/BaseAlarmViewHolder.java index 0ff25e7..a1c05b1 100644 --- a/app/src/main/java/com/philliphsu/clock2/alarms/BaseAlarmViewHolder.java +++ b/app/src/main/java/com/philliphsu/clock2/alarms/BaseAlarmViewHolder.java @@ -52,7 +52,9 @@ public abstract class BaseAlarmViewHolder extends BaseViewHolder { // TODO: Should we use VectorDrawable type? private final Drawable mDismissNowDrawable; private final Drawable mCancelSnoozeDrawable; - private final FragmentManager mFragmentManager; + + // Exposed for use by subclasses (obviously in this package. + final FragmentManager mFragmentManager; @Bind(R.id.time) TextView mTime; @Bind(R.id.on_off_switch) SwitchCompat mSwitch; diff --git a/app/src/main/java/com/philliphsu/clock2/alarms/ExpandedAlarmViewHolder.java b/app/src/main/java/com/philliphsu/clock2/alarms/ExpandedAlarmViewHolder.java index 27a8416..f0ec23c 100644 --- a/app/src/main/java/com/philliphsu/clock2/alarms/ExpandedAlarmViewHolder.java +++ b/app/src/main/java/com/philliphsu/clock2/alarms/ExpandedAlarmViewHolder.java @@ -1,7 +1,5 @@ package com.philliphsu.clock2.alarms; -import android.app.Activity; -import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.media.RingtoneManager; @@ -18,6 +16,7 @@ import com.philliphsu.clock2.Alarm; import com.philliphsu.clock2.DaysOfWeek; import com.philliphsu.clock2.OnListItemInteractionListener; import com.philliphsu.clock2.R; +import com.philliphsu.clock2.RingtonePickerDialog; import com.philliphsu.clock2.aospdatetimepicker.Utils; import com.philliphsu.clock2.util.AlarmController; @@ -115,18 +114,25 @@ public class ExpandedAlarmViewHolder extends BaseAlarmViewHolder { @OnClick(R.id.ringtone) void showRingtonePickerDialog() { - 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, getSelectedRingtoneUri()) - // Whether to show "Default" item in the list - .putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false); - // The ringtone that plays when default option is selected - //.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, DEFAULT_TONE); - // TODO: This is VERY BAD. Use a Controller/Presenter instead. - // The result will be delivered to MainActivity, and then delegated to AlarmsFragment. - ((Activity) getContext()).startActivityForResult(intent, AlarmsFragment.REQUEST_PICK_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, getSelectedRingtoneUri()) +// // Whether to show "Default" item in the list +// .putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false); +// // The ringtone that plays when default option is selected +// //.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, DEFAULT_TONE); +// // TODO: This is VERY BAD. Use a Controller/Presenter instead. +// // The result will be delivered to MainActivity, and then delegated to AlarmsFragment. +// ((Activity) getContext()).startActivityForResult(intent, AlarmsFragment.REQUEST_PICK_RINGTONE); + RingtonePickerDialog dialog = RingtonePickerDialog.newInstance(new RingtonePickerDialog.OnRingtoneSelectedListener() { + @Override + public void onRingtoneSelected(Uri ringtoneUri) { + Log.d(TAG, "Selected ringtone: " + ringtoneUri); + } + }, getSelectedRingtoneUri()); + dialog.show(mFragmentManager, "TAG"); } @OnClick(R.id.vibrate) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8a043ff..b8eec26 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -203,4 +203,5 @@ Your timer expired. Label + Ringtones