am eba0949b: Access incoming audio files after user taps Play

* commit 'eba0949bc60e9002adf0c96044677b4c281b2819':
  Access incoming audio files after user taps Play
This commit is contained in:
Shri Borde
2015-08-21 19:58:12 +00:00
committed by Android Git Automerger
6 changed files with 90 additions and 23 deletions
@@ -23,6 +23,7 @@ import android.provider.MediaStore.Video.Thumbnails;
import com.android.messaging.Factory;
import com.android.messaging.util.MediaMetadataRetrieverWrapper;
import com.android.messaging.util.MediaUtil;
import com.android.messaging.util.OsUtil;
import java.io.FileNotFoundException;
@@ -41,7 +42,7 @@ public class VideoThumbnailRequest extends ImageRequest<UriImageRequestDescripto
}
public static boolean shouldShowIncomingVideoThumbnails() {
return OsUtil.isAtLeastM();
return MediaUtil.canAutoAccessIncomingMedia();
}
@Override
@@ -269,7 +269,8 @@ public class AttachmentPreviewFactory {
final View view = layoutInflater.inflate(layoutId, parent, false /* attachToRoot */);
final AudioAttachmentView audioView = (AudioAttachmentView)
view.findViewById(R.id.audio_attachment_view);
audioView.bindMessagePartData(attachmentData, false /* incoming */);
audioView.bindMessagePartData(
attachmentData, false /* incoming */, false /* showAsSelected */);
return view;
}
@@ -41,6 +41,7 @@ import com.android.messaging.ui.mediapicker.PausableChronometer;
import com.android.messaging.util.Assert;
import com.android.messaging.util.ContentType;
import com.android.messaging.util.LogUtil;
import com.android.messaging.util.MediaUtil;
import com.android.messaging.util.UiUtils;
/**
@@ -74,11 +75,15 @@ public class AudioAttachmentView extends LinearLayout {
private int mClipPathWidth;
private int mClipPathHeight;
// Indicates whether the attachment view is to be styled as a part of an incoming message.
private boolean mShowAsIncoming;
private boolean mUseIncomingStyle;
private int mThemeColor;
private boolean mStartPlayAfterPrepare;
// should the MediaPlayer be prepared lazily when the user chooses to play the audio (as
// opposed to preparing it early, on bind)
private boolean mPrepareOnPlayback;
private boolean mPrepared;
private boolean mPlaybackFinished;
private boolean mPlaybackFinished; // Was the audio played all the way to the end
private final int mMode;
public AudioAttachmentView(final Context context, final AttributeSet attrs) {
@@ -108,7 +113,7 @@ public class AudioAttachmentView extends LinearLayout {
mPlayPauseButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
setupMediaPlayer();
// Has the MediaPlayer already been prepared?
if (mMediaPlayer != null && mPrepared) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
@@ -117,6 +122,17 @@ public class AudioAttachmentView extends LinearLayout {
} else {
playAudio();
}
} else {
// Either eager preparation is still going on (the user must have clicked
// the Play button immediately after the view is bound) or this is lazy
// preparation.
if (mStartPlayAfterPrepare) {
// The user is (starting and) pausing before the MediaPlayer is prepared
mStartPlayAfterPrepare = false;
} else {
mStartPlayAfterPrepare = true;
setupMediaPlayer();
}
}
updatePlayPauseButtonState();
}
@@ -125,26 +141,52 @@ public class AudioAttachmentView extends LinearLayout {
initializeViewsForMode();
}
private void updateChronometerVisibility(final boolean playing) {
if (mChronometer.getVisibility() == View.GONE) {
// The chronometer is always GONE for LAYOUT_MODE_SUB_COMPACT
Assert.equals(LAYOUT_MODE_SUB_COMPACT, mMode);
return;
}
if (mPrepareOnPlayback) {
// For lazy preparation, the chronometer will only be shown during playback
mChronometer.setVisibility(playing ? View.VISIBLE : View.INVISIBLE);
} else {
mChronometer.setVisibility(View.VISIBLE);
}
}
/**
* Bind the audio attachment view with a MessagePartData.
* @param incoming indicates whether the attachment view is to be styled as a part of an
* incoming message.
*/
public void bindMessagePartData(final MessagePartData messagePartData,
final boolean incoming) {
final boolean incoming, final boolean showAsSelected) {
Assert.isTrue(messagePartData == null ||
ContentType.isAudioType(messagePartData.getContentType()));
final Uri contentUri = (messagePartData == null) ? null : messagePartData.getContentUri();
bind(contentUri, incoming);
bind(contentUri, incoming, showAsSelected);
}
public void bind(final Uri dataSourceUri, final boolean incoming) {
public void bind(
final Uri dataSourceUri, final boolean incoming, final boolean showAsSelected) {
final String currentUriString = (mDataSourceUri == null) ? "" : mDataSourceUri.toString();
final String newUriString = (dataSourceUri == null) ? "" : dataSourceUri.toString();
mShowAsIncoming = incoming;
final int themeColor = ConversationDrawables.get().getConversationThemeColor();
final boolean useIncomingStyle = incoming || showAsSelected;
final boolean visualStyleChanged = mThemeColor != themeColor ||
mUseIncomingStyle != useIncomingStyle;
mUseIncomingStyle = useIncomingStyle;
mThemeColor = themeColor;
mPrepareOnPlayback = incoming && !MediaUtil.canAutoAccessIncomingMedia();
if (!TextUtils.equals(currentUriString, newUriString)) {
mDataSourceUri = dataSourceUri;
resetToZeroState();
} else if (visualStyleChanged) {
updateVisualStyle();
}
}
@@ -173,11 +215,15 @@ public class AudioAttachmentView extends LinearLayout {
releaseMediaPlayer();
}
/**
* Prepare the MediaPlayer, and if mPrepareOnPlayback, start playing the audio
*/
private void setupMediaPlayer() {
Assert.notNull(mDataSourceUri);
if (mMediaPlayer == null) {
Assert.isTrue(!mPrepared);
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(Factory.get().getApplicationContext(), mDataSourceUri);
@@ -188,6 +234,7 @@ public class AudioAttachmentView extends LinearLayout {
mChronometer.reset();
mChronometer.setBase(SystemClock.elapsedRealtime() -
mMediaPlayer.getDuration());
updateChronometerVisibility(false /* playing */);
mProgressBar.reset();
mPlaybackFinished = true;
@@ -203,16 +250,24 @@ public class AudioAttachmentView extends LinearLayout {
mProgressBar.setDuration(mMediaPlayer.getDuration());
mMediaPlayer.seekTo(0);
mPrepared = true;
if (mStartPlayAfterPrepare) {
mStartPlayAfterPrepare = false;
playAudio();
updatePlayPauseButtonState();
}
}
});
mMediaPlayer.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
mStartPlayAfterPrepare = false;
onAudioReplayError(what, extra, null);
return true;
}
});
mMediaPlayer.prepareAsync();
} catch (final Exception exception) {
onAudioReplayError(0, 0, exception);
@@ -226,13 +281,17 @@ public class AudioAttachmentView extends LinearLayout {
mMediaPlayer.release();
mMediaPlayer = null;
mPrepared = false;
mStartPlayAfterPrepare = false;
mPlaybackFinished = false;
mChronometer.reset();
mProgressBar.reset();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// The view must have scrolled off. Stop playback.
releaseMediaPlayer();
}
@@ -258,22 +317,23 @@ public class AudioAttachmentView extends LinearLayout {
}
private void updatePlayPauseButtonState() {
if (mMediaPlayer == null || !mMediaPlayer.isPlaying()) {
mPlayPauseButton.setDisplayedChild(PLAY_BUTTON);
} else {
final boolean playing = mMediaPlayer != null && mMediaPlayer.isPlaying();
updateChronometerVisibility(playing);
if (mStartPlayAfterPrepare || playing) {
mPlayPauseButton.setDisplayedChild(PAUSE_BUTTON);
} else {
mPlayPauseButton.setDisplayedChild(PLAY_BUTTON);
}
}
private void resetToZeroState() {
// Release the media player so it may be set up with the new audio source.
releaseMediaPlayer();
mChronometer.reset();
mProgressBar.reset();
updateVisualStyle();
updateChronometerVisibility(false /* playing */);
if (mDataSourceUri != null) {
// Re-ensure the media player, so we can read the duration of the audio.
if (mDataSourceUri != null && !mPrepareOnPlayback) {
// Prepare the media player, so we can read the duration of the audio.
setupMediaPlayer();
}
}
@@ -284,13 +344,13 @@ public class AudioAttachmentView extends LinearLayout {
return;
}
if (mShowAsIncoming) {
if (mUseIncomingStyle) {
mChronometer.setTextColor(getResources().getColor(R.color.message_text_color_incoming));
} else {
mChronometer.setTextColor(getResources().getColor(R.color.message_text_color_outgoing));
}
mProgressBar.setVisualStyle(mShowAsIncoming);
mPlayPauseButton.setVisualStyle(mShowAsIncoming);
mProgressBar.setVisualStyle(mUseIncomingStyle);
mPlayPauseButton.setVisualStyle(mUseIncomingStyle);
updatePlayPauseButtonState();
}
@@ -1110,7 +1110,7 @@ public class ConversationMessageView extends FrameLayout implements View.OnClick
@Override
public void bindView(final View view, final MessagePartData attachment) {
final AudioAttachmentView audioView = (AudioAttachmentView) view;
audioView.bindMessagePartData(attachment, isSelected() || mData.getIsIncoming());
audioView.bindMessagePartData(attachment, mData.getIsIncoming(), isSelected());
audioView.setBackground(ConversationDrawables.get().getBubbleDrawable(
isSelected(), mData.getIsIncoming(), false /* needArrow */,
mData.hasIncomingErrorStatus()));
@@ -1118,7 +1118,7 @@ public class ConversationMessageView extends FrameLayout implements View.OnClick
@Override
public void unbind(final View view) {
((AudioAttachmentView) view).bindMessagePartData(null, mData.getIsIncoming());
((AudioAttachmentView) view).bindMessagePartData(null, mData.getIsIncoming(), false);
}
};
@@ -465,7 +465,8 @@ public class ConversationListItemView extends FrameLayout implements OnClickList
int audioPreviewVisiblity = GONE;
if (previewUri != null && !TextUtils.isEmpty(previewContentType)) {
if (ContentType.isAudioType(previewContentType)) {
mAudioAttachmentView.bind(previewUri, false);
boolean incoming = !(mData.getShowDraft() || mData.getIsMessageTypeOutgoing());
mAudioAttachmentView.bind(previewUri, incoming, false);
audioPreviewVisiblity = VISIBLE;
} else if (ContentType.isVideoType(previewContentType)) {
previewImageUri = UriUtil.getUriForResourceId(
@@ -33,4 +33,8 @@ public abstract class MediaUtil {
*/
public abstract void playSound(final Context context, final int resId,
final OnCompletionListener completionListener);
public static boolean canAutoAccessIncomingMedia() {
return OsUtil.isAtLeastM();
}
}