diff --git a/app/src/main/java/com/philliphsu/clock2/RingtonePickerDialog.java b/app/src/main/java/com/philliphsu/clock2/RingtonePickerDialog.java index 0a739a0..5cd4a58 100644 --- a/app/src/main/java/com/philliphsu/clock2/RingtonePickerDialog.java +++ b/app/src/main/java/com/philliphsu/clock2/RingtonePickerDialog.java @@ -2,14 +2,14 @@ package com.philliphsu.clock2; import android.content.DialogInterface; import android.database.Cursor; -import android.media.AudioManager; -import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; +import com.philliphsu.clock2.ringtone.RingtoneLoop; + /** * Created by Phillip Hsu on 9/3/2016. *
@@ -31,7 +31,7 @@ public class RingtonePickerDialog extends BaseAlertDialogFragment { private RingtoneManager mRingtoneManager; private OnRingtoneSelectedListener mOnRingtoneSelectedListener; private Uri mRingtoneUri; - private Ringtone mRingtone; + private RingtoneLoop mRingtone; public interface OnRingtoneSelectedListener { void onRingtoneSelected(Uri ringtoneUri); @@ -66,12 +66,12 @@ public class RingtonePickerDialog extends BaseAlertDialogFragment { .setSingleChoiceItems(cursor, checkedItem, labelColumn, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + if (mRingtone != null) { + destroyLocalPlayer(); + } // 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 = new RingtoneLoop(getActivity(), mRingtoneUri); mRingtone.play(); } }); @@ -81,9 +81,7 @@ public class RingtonePickerDialog extends BaseAlertDialogFragment { @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); - if (mRingtone != null && mRingtone.isPlaying()) { - mRingtone.stop(); - } + destroyLocalPlayer(); } @Override @@ -98,4 +96,11 @@ public class RingtonePickerDialog extends BaseAlertDialogFragment { public void setOnRingtoneSelectedListener(OnRingtoneSelectedListener onRingtoneSelectedListener) { mOnRingtoneSelectedListener = onRingtoneSelectedListener; } + + private void destroyLocalPlayer() { + if (mRingtone != null) { + mRingtone.stop(); + mRingtone = null; + } + } } diff --git a/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneLoop.java b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneLoop.java new file mode 100644 index 0000000..7e87b5a --- /dev/null +++ b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneLoop.java @@ -0,0 +1,63 @@ +package com.philliphsu.clock2.ringtone; + +import android.content.Context; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.net.Uri; + +import java.io.IOException; + +/** + * Created by Phillip Hsu on 9/5/2016. + * + * A MediaPlayer configured to play a ringtone in a loop. + */ +public final class RingtoneLoop { + + private final Context mContext; + private final AudioManager mAudioManager; + private final Uri mUri; + + private MediaPlayer mMediaPlayer; + + public RingtoneLoop(Context context, Uri uri) { + mContext = context; + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + mUri = uri; + } + + public void play() { + try { + mMediaPlayer = new MediaPlayer(); + mMediaPlayer.setDataSource(mContext, mUri); + if (mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) { + // "Must call this method before prepare() or prepareAsync() in order + // for the target stream type to become effective thereafter." + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); + mMediaPlayer.setLooping(true); + // There is prepare() and prepareAsync(). + // "For files, it is OK to call prepare(), which blocks until + // MediaPlayer is ready for playback." + mMediaPlayer.prepare(); + mMediaPlayer.start(); + } + } catch (SecurityException | IOException e) { + destroyLocalPlayer(); + } + } + + public void stop() { + if (mMediaPlayer != null) { + destroyLocalPlayer(); + } + } + + private void destroyLocalPlayer() { + if (mMediaPlayer != null) { + mMediaPlayer.reset(); + mMediaPlayer.release(); + mMediaPlayer = null; + } + } + +} diff --git a/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java index e8ea5a1..a13860b 100644 --- a/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java +++ b/app/src/main/java/com/philliphsu/clock2/ringtone/RingtoneService.java @@ -7,7 +7,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.media.AudioManager; -import android.media.MediaPlayer; import android.net.Uri; import android.os.Handler; import android.os.IBinder; @@ -19,7 +18,6 @@ import android.util.Log; import com.philliphsu.clock2.R; import com.philliphsu.clock2.util.LocalBroadcastHelper; -import java.io.IOException; import java.util.concurrent.TimeUnit; /** @@ -41,7 +39,7 @@ public abstract class RingtoneService