summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java')
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java395
1 files changed, 334 insertions, 61 deletions
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
index d5db60846..77dd9cc4b 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
@@ -19,12 +19,9 @@ package com.android.dialer.voicemail.listui;
import android.app.FragmentManager;
import android.content.Context;
import android.database.Cursor;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.provider.VoicemailContract;
+import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.support.v4.util.Pair;
import android.util.AttributeSet;
@@ -32,13 +29,18 @@ import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.voicemail.listui.NewVoicemailViewHolder.NewVoicemailViewHolderListener;
import com.android.dialer.voicemail.model.VoicemailEntry;
+import java.util.Locale;
/**
* The view of the media player that is visible when a {@link NewVoicemailViewHolder} is expanded.
@@ -46,13 +48,18 @@ import com.android.dialer.voicemail.model.VoicemailEntry;
public class NewVoicemailMediaPlayerView extends LinearLayout {
private ImageButton playButton;
+ private ImageButton pauseButton;
private ImageButton speakerButton;
private ImageButton phoneButton;
private ImageButton deleteButton;
+ private TextView currentSeekBarPosition;
+ private SeekBar seekBarView;
private TextView totalDurationView;
private Uri voicemailUri;
private FragmentManager fragmentManager;
- private MediaPlayer mediaPlayer;
+ private NewVoicemailViewHolder newVoicemailViewHolder;
+ private NewVoicemailMediaPlayer mediaPlayer;
+ private NewVoicemailViewHolderListener newVoicemailViewHolderListener;
public NewVoicemailMediaPlayerView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -72,6 +79,9 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
private void initializeMediaPlayerButtonsAndViews() {
playButton = findViewById(R.id.playButton);
+ pauseButton = findViewById(R.id.pauseButton);
+ currentSeekBarPosition = findViewById(R.id.playback_position_text);
+ seekBarView = findViewById(R.id.playback_seek);
speakerButton = findViewById(R.id.speakerButton);
phoneButton = findViewById(R.id.phoneButton);
deleteButton = findViewById(R.id.deleteButton);
@@ -80,13 +90,202 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
private void setupListenersForMediaPlayerButtons() {
playButton.setOnClickListener(playButtonListener);
+ pauseButton.setOnClickListener(pauseButtonListener);
+ seekBarView.setOnSeekBarChangeListener(seekbarChangeListener);
speakerButton.setOnClickListener(speakerButtonListener);
phoneButton.setOnClickListener(phoneButtonListener);
deleteButton.setOnClickListener(deleteButtonListener);
}
+ public void reset() {
+ LogUtil.i("NewVoicemailMediaPlayer.reset", "the uri for this is " + voicemailUri);
+ voicemailUri = null;
+ }
+
+ /**
+ * Can be called either when binding happens on the {@link NewVoicemailViewHolder} from {@link
+ * NewVoicemailAdapter} or when a user expands a {@link NewVoicemailViewHolder}. During the
+ * binding, since {@link NewVoicemailMediaPlayerView} is part of {@link NewVoicemailViewHolder},
+ * we have to ensure that during the binding the values from the {@link NewVoicemailAdapter} are
+ * also propogated down to the {@link NewVoicemailMediaPlayerView} via {@link
+ * NewVoicemailViewHolder}. In the case of when the {@link NewVoicemailViewHolder} is expanded,
+ * the most recent value and states from the {@link NewVoicemailAdapter} are set for the expanded
+ * {@link NewVoicemailMediaPlayerView}.
+ *
+ * @param viewHolder
+ * @param voicemailEntryFromAdapter are the voicemail related values from the {@link
+ * AnnotatedCallLog} converted into {@link VoicemailEntry} format.
+ * @param fragmentManager
+ * @param mp the media player passed down from the adapter
+ * @param listener
+ */
+ void bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView(
+ NewVoicemailViewHolder viewHolder,
+ @NonNull VoicemailEntry voicemailEntryFromAdapter,
+ @NonNull FragmentManager fragmentManager,
+ NewVoicemailMediaPlayer mp,
+ NewVoicemailViewHolderListener listener) {
+
+ Assert.isNotNull(voicemailEntryFromAdapter);
+ Uri uri = Uri.parse(voicemailEntryFromAdapter.voicemailUri());
+ Assert.isNotNull(viewHolder);
+ Assert.isNotNull(uri);
+ Assert.isNotNull(listener);
+ Assert.isNotNull(totalDurationView);
+ Assert.checkArgument(uri.equals(viewHolder.getViewHolderVoicemailUri()));
+
+ LogUtil.i(
+ "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
+ "Updating the viewholder:%d mediaPlayerView with uri value:%s",
+ viewHolder.getViewHolderId(),
+ uri.toString());
+
+ this.fragmentManager = fragmentManager;
+
+ newVoicemailViewHolder = viewHolder;
+ newVoicemailViewHolderListener = listener;
+ mediaPlayer = mp;
+ voicemailUri = uri;
+ totalDurationView.setText(
+ VoicemailEntryText.getVoicemailDuration(getContext(), voicemailEntryFromAdapter));
+ // Not sure if these are needed, but it'll ensure that onInflate() has atleast happened.
+ initializeMediaPlayerButtonsAndViews();
+ setupListenersForMediaPlayerButtons();
+
+ // During the binding we only send a request to the adapter to tell us what the
+ // state of the media player should be and call that function.
+ // This could be the paused state, or the playing state of the resume state.
+ // Our job here is only to send the request upto the adapter and have it decide what we should
+ // do.
+ LogUtil.i(
+ "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
+ "Updating media player values for id:" + viewHolder.getViewHolderId());
+
+ // During the binding make sure that the first time we just set the mediaplayer view
+ // This does not take care of the constant update
+ if (mp.isPlaying() && mp.getLastPlayedOrPlayingVoicemailUri().equals(voicemailUri)) {
+ Assert.checkArgument(
+ mp.getLastPlayedOrPlayingVoicemailUri()
+ .equals(mp.getLastPreparedOrPreparingToPlayVoicemailUri()));
+ LogUtil.i(
+ "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
+ "show playing state");
+ playButton.setVisibility(GONE);
+ pauseButton.setVisibility(VISIBLE);
+ currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mp.getCurrentPosition()));
+
+ if (seekBarView.getMax() != mp.getDuration()) {
+ seekBarView.setMax(mp.getDuration());
+ }
+ seekBarView.setProgress(mp.getCurrentPosition());
+
+ } else if (mediaPlayer.isPaused() && mp.getLastPausedVoicemailUri().equals(voicemailUri)) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
+ "show paused state");
+ Assert.checkArgument(viewHolder.getViewHolderVoicemailUri().equals(voicemailUri));
+ playButton.setVisibility(VISIBLE);
+ pauseButton.setVisibility(GONE);
+ currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mp.getCurrentPosition()));
+ if (seekBarView.getMax() != mp.getDuration()) {
+ seekBarView.setMax(mp.getDuration());
+ }
+ seekBarView.setProgress(mp.getCurrentPosition());
+
+ } else {
+ LogUtil.i(
+ "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
+ "show reset state");
+ playButton.setVisibility(VISIBLE);
+ pauseButton.setVisibility(GONE);
+ seekBarView.setProgress(0);
+ seekBarView.setMax(100);
+ currentSeekBarPosition.setText(formatAsMinutesAndSeconds(0));
+ }
+ }
+
+ private final OnSeekBarChangeListener seekbarChangeListener =
+ new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBarfromProgress, int progress, boolean fromUser) {
+ // TODO(uabdullah): Only for debugging purposes, to be removed.
+ if (progress < 100) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.seekbarChangeListener",
+ "onProgressChanged, progress:%d, seekbarMax: %d, fromUser:%b",
+ progress,
+ seekBarfromProgress.getMax(),
+ fromUser);
+ }
+
+ if (fromUser) {
+ mediaPlayer.seekTo(progress);
+ currentSeekBarPosition.setText(formatAsMinutesAndSeconds(progress));
+ }
+ }
+
+ @Override
+ // TODO(uabdullah): Handle this case
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ LogUtil.i("NewVoicemailMediaPlayer.onStartTrackingTouch", "does nothing for now");
+ }
+
+ @Override
+ // TODO(uabdullah): Handle this case
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ LogUtil.i("NewVoicemailMediaPlayer.onStopTrackingTouch", "does nothing for now");
+ }
+ };
+
+ private final View.OnClickListener pauseButtonListener =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.pauseButtonListener",
+ "pauseMediaPlayerAndSetPausedStateOfViewHolder button for voicemailUri: %s",
+ voicemailUri.toString());
+
+ Assert.checkArgument(playButton.getVisibility() == GONE);
+ Assert.checkArgument(mediaPlayer != null);
+ Assert.checkArgument(
+ mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals((voicemailUri)),
+ "the voicemail being played is the only voicemail that should"
+ + " be paused. last played voicemail:%s, uri:%s",
+ mediaPlayer.getLastPlayedOrPlayingVoicemailUri().toString(),
+ voicemailUri.toString());
+ Assert.checkArgument(
+ newVoicemailViewHolder.getViewHolderVoicemailUri().equals(voicemailUri),
+ "viewholder uri and mediaplayer view should be the same.");
+ newVoicemailViewHolderListener.pauseViewHolder(newVoicemailViewHolder);
+ }
+ };
+
private final View.OnClickListener playButtonListener =
- view -> playVoicemailWhenAvailableLocally();
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.playButtonListener",
+ "play button for voicemailUri: %s",
+ voicemailUri.toString());
+ if (mediaPlayer.getLastPausedVoicemailUri() != null
+ && mediaPlayer
+ .getLastPausedVoicemailUri()
+ .toString()
+ .contentEquals(voicemailUri.toString())) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.playButtonListener",
+ "resume playing voicemailUri: %s",
+ voicemailUri.toString());
+
+ newVoicemailViewHolderListener.resumePausedViewHolder(newVoicemailViewHolder);
+
+ } else {
+ playVoicemailWhenAvailableLocally();
+ }
+ }
+ };
/**
* Plays the voicemail when we are able to play the voicemail locally from the device. This
@@ -113,7 +312,7 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
Uri uri = contextUriPair.second;
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
- if (cursor != null && cursor.moveToNext()) {
+ if (cursor != null && cursor.moveToFirst()) {
return new Pair<>(
cursor.getInt(cursor.getColumnIndex(VoicemailContract.Voicemails.HAS_CONTENT)) == 1,
uri);
@@ -137,17 +336,18 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
if (voicemailAvailableLocally) {
try {
- mediaPlayer = new MediaPlayer();
- mediaPlayer.setOnPreparedListener(onPreparedListener);
- mediaPlayer.setOnErrorListener(onErrorListener);
- mediaPlayer.setOnCompletionListener(onCompletionListener);
-
- mediaPlayer.reset();
- mediaPlayer.setDataSource(getContext(), uri);
-
- mediaPlayer.prepareAsync();
+ Assert.checkArgument(mediaPlayer != null, "media player should not have been null");
+ mediaPlayer.prepareMediaPlayerAndPlayVoicemailWhenReady(getContext(), uri);
} catch (Exception e) {
- LogUtil.e("NewVoicemailMediaPlayer.prepareMediaPlayer", "IOException " + e);
+ LogUtil.e(
+ "NewVoicemailMediaPlayer.prepareMediaPlayer",
+ "Exception when mediaPlayer.prepareMediaPlayerAndPlayVoicemailWhenReady"
+ + "(getContext(), uri)\n"
+ + e
+ + "\n uri:"
+ + uri
+ + "context should not be null, its value is :"
+ + getContext());
}
} else {
// TODO(a bug): Add logic for downloading voicemail content from the server.
@@ -189,57 +389,130 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
}
};
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- OnCompletionListener onCompletionListener =
- new OnCompletionListener() {
+ /**
+ * This is only called to update the media player view of the seekbar, and the duration and the
+ * play button. For constant updates the adapter should seek track. This is the state when a
+ * voicemail is playing.
+ */
+ public void updateSeekBarDurationAndShowPlayButton(NewVoicemailMediaPlayer mp) {
+ if (!mp.isPlaying()) {
+ return;
+ }
- @Override
- public void onCompletion(MediaPlayer mp) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.onCompletionListener",
- "completed playing voicemailUri: %s",
- voicemailUri.toString());
- }
- };
+ playButton.setVisibility(GONE);
+ pauseButton.setVisibility(VISIBLE);
- private final OnPreparedListener onPreparedListener =
- new OnPreparedListener() {
+ Assert.checkArgument(
+ mp.equals(mediaPlayer), "there should only be one instance of a media player");
+ Assert.checkArgument(
+ mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri().equals(voicemailUri));
+ Assert.checkArgument(mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals(voicemailUri));
+ Assert.isNotNull(mediaPlayer, "media player should have been set on bind");
+ Assert.checkArgument(mediaPlayer.isPlaying());
+ Assert.checkArgument(mediaPlayer.getCurrentPosition() >= 0);
+ Assert.checkArgument(mediaPlayer.getDuration() >= 0);
+ Assert.checkArgument(playButton.getVisibility() == GONE);
+ Assert.checkArgument(pauseButton.getVisibility() == VISIBLE);
+ Assert.checkArgument(seekBarView.getVisibility() == VISIBLE);
+ Assert.checkArgument(currentSeekBarPosition.getVisibility() == VISIBLE);
- @Override
- public void onPrepared(MediaPlayer mp) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.onPreparedListener",
- "about to play voicemailUri: %s",
- voicemailUri.toString());
- mediaPlayer.start();
- }
- };
+ currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mediaPlayer.getCurrentPosition()));
+ if (seekBarView.getMax() != mediaPlayer.getDuration()) {
+ seekBarView.setMax(mediaPlayer.getDuration());
+ }
+ seekBarView.setProgress(mediaPlayer.getCurrentPosition());
+ }
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- OnErrorListener onErrorListener =
- new OnErrorListener() {
- @Override
- public boolean onError(MediaPlayer mp, int what, int extra) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.onErrorListener",
- "error playing voicemailUri: %s",
- voicemailUri.toString());
- return false;
- }
- };
+ /**
+ * What the default state of an expanded media player view should look like.
+ *
+ * @param currentlyExpandedViewHolderOnScreen
+ * @param mediaPlayer
+ */
+ public void setToResetState(
+ NewVoicemailViewHolder currentlyExpandedViewHolderOnScreen,
+ NewVoicemailMediaPlayer mediaPlayer) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.setToResetState",
+ "update the seekbar for viewholder id:%d, mediaplayer view uri:%s, play button "
+ + "visible:%b, pause button visible:%b",
+ currentlyExpandedViewHolderOnScreen.getViewHolderId(),
+ String.valueOf(voicemailUri),
+ playButton.getVisibility() == VISIBLE,
+ pauseButton.getVisibility() == VISIBLE);
- void setFragmentManager(FragmentManager fragmentManager) {
- this.fragmentManager = fragmentManager;
+ if (playButton.getVisibility() == GONE) {
+ playButton.setVisibility(VISIBLE);
+ pauseButton.setVisibility(GONE);
+ }
+
+ Assert.checkArgument(playButton.getVisibility() == VISIBLE);
+ Assert.checkArgument(pauseButton.getVisibility() == GONE);
+
+ Assert.checkArgument(
+ !mediaPlayer.isPlaying(),
+ "when resetting an expanded " + "state, there should be no voicemail playing");
+
+ Assert.checkArgument(
+ mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals(Uri.EMPTY),
+ "reset should have been called before updating its media player view");
+ currentSeekBarPosition.setText(formatAsMinutesAndSeconds(0));
+ seekBarView.setProgress(0);
+ seekBarView.setMax(100);
}
- void setVoicemailEntryValues(VoicemailEntry voicemailEntry) {
- Assert.isNotNull(voicemailEntry);
- Uri uri = Uri.parse(voicemailEntry.voicemailUri());
- Assert.isNotNull(uri);
- Assert.isNotNull(totalDurationView);
+ public void setToPausedState(Uri toPausedState, NewVoicemailMediaPlayer mp) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.setToPausedState",
+ "toPausedState uri:%s, play button visible:%b, pause button visible:%b",
+ toPausedState == null ? "null" : voicemailUri.toString(),
+ playButton.getVisibility() == VISIBLE,
+ pauseButton.getVisibility() == VISIBLE);
- voicemailUri = uri;
- totalDurationView.setText(
- VoicemailEntryText.getVoicemailDuration(getContext(), voicemailEntry));
+ playButton.setVisibility(VISIBLE);
+ pauseButton.setVisibility(GONE);
+
+ currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mediaPlayer.getCurrentPosition()));
+ if (seekBarView.getMax() != mediaPlayer.getDuration()) {
+ seekBarView.setMax(mediaPlayer.getDuration());
+ }
+ seekBarView.setProgress(mediaPlayer.getCurrentPosition());
+
+ Assert.checkArgument(voicemailUri.equals(toPausedState));
+ Assert.checkArgument(!mp.isPlaying());
+ Assert.checkArgument(
+ mp.equals(mediaPlayer), "there should only be one instance of a media player");
+ Assert.checkArgument(
+ this.mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri().equals(voicemailUri));
+ Assert.checkArgument(
+ this.mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals(voicemailUri));
+ Assert.checkArgument(this.mediaPlayer.getLastPausedVoicemailUri().equals(voicemailUri));
+ Assert.isNotNull(this.mediaPlayer, "media player should have been set on bind");
+ Assert.checkArgument(this.mediaPlayer.getCurrentPosition() >= 0);
+ Assert.checkArgument(this.mediaPlayer.getDuration() >= 0);
+ Assert.checkArgument(playButton.getVisibility() == VISIBLE);
+ Assert.checkArgument(pauseButton.getVisibility() == GONE);
+ Assert.checkArgument(seekBarView.getVisibility() == VISIBLE);
+ Assert.checkArgument(currentSeekBarPosition.getVisibility() == VISIBLE);
+ }
+
+ @NonNull
+ public Uri getVoicemailUri() {
+ return voicemailUri;
+ }
+
+ private String formatAsMinutesAndSeconds(int millis) {
+ int seconds = millis / 1000;
+ int minutes = seconds / 60;
+ seconds -= minutes * 60;
+ if (minutes > 99) {
+ minutes = 99;
+ }
+ return String.format(Locale.US, "%02d:%02d", minutes, seconds);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ void setFragmentManager(FragmentManager fragmentManager) {
+ this.fragmentManager = fragmentManager;
}
}