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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user