blob: 6b8307399218b17234edb8a430e2c930ee4dc89a [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.music;
import android.app.Activity;
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.media.AudioManager;
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.browse.MediaBrowser;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.text.Layout;
import android.text.TextUtils.TruncateAt;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import com.android.music.utils.LogHelper;
import com.android.music.utils.MediaIDHelper;
import com.android.music.utils.MusicProvider;
/*
This is the Now Playing Activity
*/
public class MediaPlaybackActivity
extends Activity implements View.OnTouchListener, View.OnLongClickListener {
private static final String TAG = LogHelper.makeLogTag(MediaPlaybackActivity.class);
private long mStartSeekPos = 0;
private long mLastSeekEventTime;
private RepeatingImageButton mPrevButton;
private ImageButton mPlayPauseButton;
private RepeatingImageButton mNextButton;
private ImageButton mRepeatButton;
private ImageButton mShuffleButton;
private ImageButton mQueueButton;
private int mTouchSlop;
private ImageView mAlbumArt;
private TextView mCurrentTime;
private TextView mTotalTime;
private TextView mArtistName;
private TextView mAlbumName;
private TextView mTrackName;
private LinearLayout mTrackInfo;
private ProgressBar mProgress;
private BitmapDrawable mDefaultAlbumArt;
private Toast mToast;
private MediaBrowser mMediaBrowser;
private final Handler mHandler = new Handler();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
LogHelper.d(TAG, "onCreate()");
super.onCreate(icicle);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.audio_player);
mCurrentTime = (TextView) findViewById(R.id.currenttime);
mTotalTime = (TextView) findViewById(R.id.totaltime);
mProgress = (ProgressBar) findViewById(android.R.id.progress);
mAlbumArt = (ImageView) findViewById(R.id.album);
mArtistName = (TextView) findViewById(R.id.artistname);
mAlbumName = (TextView) findViewById(R.id.albumname);
mTrackName = (TextView) findViewById(R.id.trackname);
mTrackInfo = (LinearLayout) findViewById(R.id.trackinfo);
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.albumart_mp_unknown);
mDefaultAlbumArt = new BitmapDrawable(getResources(), b);
// no filter or dither, it's a lot faster and we can't tell the difference
mDefaultAlbumArt.setFilterBitmap(false);
mDefaultAlbumArt.setDither(false);
/* Set metadata listeners */
View v = (View) mArtistName.getParent();
v.setOnTouchListener(this);
v.setOnLongClickListener(this);
v = (View) mAlbumName.getParent();
v.setOnTouchListener(this);
v.setOnLongClickListener(this);
v = (View) mTrackName.getParent();
v.setOnTouchListener(this);
v.setOnLongClickListener(this);
/* Set button listeners */
mPrevButton = (RepeatingImageButton) findViewById(R.id.prev);
mPrevButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (getMediaController() == null) return;
if (getMediaController().getPlaybackState().getPosition() < 2000) {
getMediaController().getTransportControls().skipToPrevious();
} else {
getMediaController().getTransportControls().seekTo(0);
getMediaController().getTransportControls().play();
}
}
});
mPrevButton.setRepeatListener(new RepeatingImageButton.RepeatListener() {
public void onRepeat(View v, long howlong, int repcnt) {
scanBackward(repcnt, howlong);
}
}, 260);
mPlayPauseButton = (ImageButton) findViewById(R.id.pause);
mPlayPauseButton.requestFocus();
mPlayPauseButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (getMediaController() != null) {
if (getMediaController().getPlaybackState().getState()
!= PlaybackState.STATE_PLAYING) {
getMediaController().getTransportControls().play();
} else {
getMediaController().getTransportControls().pause();
}
}
}
});
mNextButton = (RepeatingImageButton) findViewById(R.id.next);
mNextButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (getMediaController() == null) return;
getMediaController().getTransportControls().skipToNext();
}
});
mNextButton.setRepeatListener(new RepeatingImageButton.RepeatListener() {
public void onRepeat(View v, long howlong, int repcnt) {
scanForward(repcnt, howlong);
}
}, 260);
mQueueButton = (ImageButton) findViewById(R.id.curplaylist);
mQueueButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
LogHelper.d(TAG, "mQueueButton onClick");
MediaBrowser.MediaItem parentItem = new MediaBrowser.MediaItem(
new MediaDescription.Builder()
.setMediaId(MediaIDHelper.createBrowseCategoryMediaID(
MediaIDHelper.MEDIA_ID_MUSICS_BY_PLAYLIST,
MediaIDHelper.MEDIA_ID_NOW_PLAYING))
.setTitle("Now Playing")
.build(),
MediaBrowser.MediaItem.FLAG_BROWSABLE);
Intent intent = new Intent(Intent.ACTION_PICK)
.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track")
.putExtra(MusicUtils.TAG_WITH_TABS, false)
.putExtra(MusicUtils.TAG_PARENT_ITEM, parentItem);
startActivity(intent);
}
});
mShuffleButton = ((ImageButton) findViewById(R.id.shuffle));
mShuffleButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
toggleShuffle();
}
});
mRepeatButton = ((ImageButton) findViewById(R.id.repeat));
mRepeatButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
LogHelper.d(TAG, "Repeat button clicked");
if (getMediaController() == null) return;
Bundle extras = getMediaController().getExtras();
if (extras == null) return;
MediaPlaybackService.RepeatMode repeatMode =
MediaPlaybackService.RepeatMode
.values()[extras.getInt(MediaPlaybackService.REPEAT_MODE)];
MediaPlaybackService.RepeatMode nextRepeatMode;
switch (repeatMode) {
case REPEAT_NONE:
nextRepeatMode = MediaPlaybackService.RepeatMode.REPEAT_ALL;
showToast(R.string.repeat_all_notif);
break;
case REPEAT_ALL:
nextRepeatMode = MediaPlaybackService.RepeatMode.REPEAT_CURRENT;
showToast(R.string.repeat_current_notif);
break;
case REPEAT_CURRENT:
default:
nextRepeatMode = MediaPlaybackService.RepeatMode.REPEAT_NONE;
showToast(R.string.repeat_off_notif);
break;
}
setRepeatMode(nextRepeatMode);
// TODO(siyuanh): Should use a callback to register changes on service side
setRepeatButtonImage(nextRepeatMode);
}
});
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
seeker.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
boolean mmFromTouch = false;
public void onStartTrackingTouch(SeekBar bar) {
mLastSeekEventTime = 0;
mmFromTouch = true;
}
public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
if (!fromuser || (getMediaController() == null)) return;
long now = SystemClock.elapsedRealtime();
if ((now - mLastSeekEventTime) > 250) {
mLastSeekEventTime = now;
long duration = getMediaController().getMetadata().getLong(
MediaMetadata.METADATA_KEY_DURATION);
long position = duration * progress / 1000;
getMediaController().getTransportControls().seekTo(position);
// trackball event, allow progress updates
if (!mmFromTouch) {
updateProgressBar();
}
}
}
public void onStopTrackingTouch(SeekBar bar) {
mmFromTouch = false;
}
});
} else {
LogHelper.d(TAG, "Seeking not supported");
}
mProgress.setMax(1000);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
Log.d(TAG, "Creating MediaBrowser");
mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
mConnectionCallback, null);
}
// Receive callbacks from the MediaController. Here we update our state such as which queue
// is being shown, the current title and description and the PlaybackState.
private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
@Override
public void onSessionDestroyed() {
LogHelper.d(TAG, "Session destroyed. Need to fetch a new Media Session");
}
@Override
public void onPlaybackStateChanged(PlaybackState state) {
if (state == null) {
return;
}
LogHelper.d(TAG, "Received playback state change to state ", state.toString());
updateProgressBar();
setPauseButtonImage();
}
@Override
public void onMetadataChanged(MediaMetadata metadata) {
if (metadata == null) {
return;
}
LogHelper.d(TAG, "Received updated metadata: ", metadata);
updateTrackInfo();
}
};
private MediaBrowser.ConnectionCallback mConnectionCallback =
new MediaBrowser.ConnectionCallback() {
@Override
public void onConnected() {
Log.d(TAG, "onConnected: session token " + mMediaBrowser.getSessionToken());
if (mMediaBrowser.getSessionToken() == null) {
throw new IllegalArgumentException("No Session token");
}
MediaController mediaController = new MediaController(
MediaPlaybackActivity.this, mMediaBrowser.getSessionToken());
mediaController.registerCallback(mMediaControllerCallback);
MediaPlaybackActivity.this.setMediaController(mediaController);
mRepeatButton.setVisibility(View.VISIBLE);
mShuffleButton.setVisibility(View.VISIBLE);
mQueueButton.setVisibility(View.VISIBLE);
setRepeatButtonImage(null);
setShuffleButtonImage();
setPauseButtonImage();
updateTrackInfo();
mHandler.post(new Runnable() {
@Override
public void run() {
long delay = updateProgressBar();
mHandler.postDelayed(this, delay);
}
});
}
@Override
public void onConnectionFailed() {
Log.d(TAG, "onConnectionFailed");
}
@Override
public void onConnectionSuspended() {
Log.d(TAG, "onConnectionSuspended");
mHandler.removeCallbacksAndMessages(null);
MediaPlaybackActivity.this.setMediaController(null);
}
};
int mInitialX = -1;
int mLastX = -1;
int mTextWidth = 0;
int mViewWidth = 0;
boolean mDraggingLabel = false;
TextView textViewForContainer(View v) {
View vv = v.findViewById(R.id.artistname);
if (vv != null) return (TextView) vv;
vv = v.findViewById(R.id.albumname);
if (vv != null) return (TextView) vv;
vv = v.findViewById(R.id.trackname);
if (vv != null) return (TextView) vv;
return null;
}
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
TextView tv = textViewForContainer(v);
if (tv == null) {
return false;
}
if (action == MotionEvent.ACTION_DOWN) {
v.setBackgroundColor(0xff606060);
mInitialX = mLastX = (int) event.getX();
mDraggingLabel = false;
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
v.setBackgroundColor(0);
if (mDraggingLabel) {
Message msg = mLabelScroller.obtainMessage(0, tv);
mLabelScroller.sendMessageDelayed(msg, 1000);
}
} else if (action == MotionEvent.ACTION_MOVE) {
if (mDraggingLabel) {
int scrollx = tv.getScrollX();
int x = (int) event.getX();
int delta = mLastX - x;
if (delta != 0) {
mLastX = x;
scrollx += delta;
if (scrollx > mTextWidth) {
// scrolled the text completely off the view to the left
scrollx -= mTextWidth;
scrollx -= mViewWidth;
}
if (scrollx < -mViewWidth) {
// scrolled the text completely off the view to the right
scrollx += mViewWidth;
scrollx += mTextWidth;
}
tv.scrollTo(scrollx, 0);
}
return true;
}
int delta = mInitialX - (int) event.getX();
if (Math.abs(delta) > mTouchSlop) {
// start moving
mLabelScroller.removeMessages(0, tv);
// Only turn ellipsizing off when it's not already off, because it
// causes the scroll position to be reset to 0.
if (tv.getEllipsize() != null) {
tv.setEllipsize(null);
}
Layout ll = tv.getLayout();
// layout might be null if the text just changed, or ellipsizing
// was just turned off
if (ll == null) {
return false;
}
// get the non-ellipsized line width, to determine whether scrolling
// should even be allowed
mTextWidth = (int) tv.getLayout().getLineWidth(0);
mViewWidth = tv.getWidth();
if (mViewWidth > mTextWidth) {
tv.setEllipsize(TruncateAt.END);
v.cancelLongPress();
return false;
}
mDraggingLabel = true;
tv.setHorizontalFadingEdgeEnabled(true);
v.cancelLongPress();
return true;
}
}
return false;
}
Handler mLabelScroller = new Handler() {
@Override
public void handleMessage(Message msg) {
TextView tv = (TextView) msg.obj;
int x = tv.getScrollX();
x = x * 3 / 4;
tv.scrollTo(x, 0);
if (x == 0) {
tv.setEllipsize(TruncateAt.END);
} else {
Message newmsg = obtainMessage(0, tv);
mLabelScroller.sendMessageDelayed(newmsg, 15);
}
}
};
public boolean onLongClick(View view) {
CharSequence title = null;
String mime = null;
String query = null;
if (getMediaController() == null) {
LogHelper.d(TAG, "No media controller avalable yet");
return true;
}
MediaMetadata metadata = getMediaController().getMetadata();
if (metadata == null) {
LogHelper.d(TAG, "No metadata avalable yet");
return true;
}
String artist = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
String album = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
String song = metadata.getString(MediaMetadata.METADATA_KEY_TITLE);
long audioid = metadata.getLong(MediaMetadata.METADATA_KEY_MEDIA_ID);
if (album == null && artist == null && song != null && song.startsWith("recording")) {
LogHelper.d(TAG, "Item is not music");
return false;
}
if (audioid < 0) {
return false;
}
boolean knownartist = (artist != null) && !MediaStore.UNKNOWN_STRING.equals(artist);
boolean knownalbum = (album != null) && !MediaStore.UNKNOWN_STRING.equals(album);
if (knownartist && view.equals(mArtistName.getParent())) {
title = artist;
query = artist;
mime = MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE;
} else if (knownalbum && view.equals(mAlbumName.getParent())) {
title = album;
if (knownartist) {
query = artist + " " + album;
} else {
query = album;
}
mime = MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE;
} else if (view.equals(mTrackName.getParent()) || !knownartist || !knownalbum) {
if ((song == null) || MediaStore.UNKNOWN_STRING.equals(song)) {
// A popup of the form "Search for null/'' using ..." is pretty
// unhelpful, plus, we won't find any way to buy it anyway.
return true;
}
title = song;
if (knownartist) {
query = artist + " " + song;
} else {
query = song;
}
mime = "audio/*"; // the specific type doesn't matter, so don't bother retrieving it
} else {
throw new RuntimeException("shouldn't be here");
}
title = getString(R.string.mediasearch, title);
Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);
i.putExtra(SearchManager.QUERY, query);
if (knownartist) {
i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
}
if (knownalbum) {
i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, album);
}
i.putExtra(MediaStore.EXTRA_MEDIA_TITLE, song);
i.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, mime);
startActivity(Intent.createChooser(i, title));
return true;
}
@Override
public void onStart() {
LogHelper.d(TAG, "onStart()");
super.onStart();
mMediaBrowser.connect();
}
@Override
public void onStop() {
LogHelper.d(TAG, "onStop()");
mMediaBrowser.disconnect();
super.onStop();
}
@Override
public void onResume() {
LogHelper.d(TAG, "onResume()");
super.onResume();
updateTrackInfo();
setPauseButtonImage();
}
@Override
public void onDestroy() {
LogHelper.d(TAG, "onDestroy()");
super.onDestroy();
}
private void scanBackward(int repcnt, long delta) {
if (getMediaController() == null) return;
if (repcnt == 0) {
mStartSeekPos = getMediaController().getPlaybackState().getPosition();
mLastSeekEventTime = 0;
} else {
if (delta < 5000) {
// seek at 10x speed for the first 5 seconds
delta = delta * 10;
} else {
// seek at 40x after that
delta = 50000 + (delta - 5000) * 40;
}
long newpos = mStartSeekPos - delta;
if (newpos < 0) {
// move to previous track
getMediaController().getTransportControls().skipToPrevious();
long duration = getMediaController().getMetadata().getLong(
MediaMetadata.METADATA_KEY_DURATION);
mStartSeekPos += duration;
newpos += duration;
}
if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
getMediaController().getTransportControls().seekTo(newpos);
mLastSeekEventTime = delta;
}
updateProgressBar();
}
}
private void scanForward(int repcnt, long delta) {
if (getMediaController() == null) return;
if (repcnt == 0) {
mStartSeekPos = getMediaController().getPlaybackState().getPosition();
mLastSeekEventTime = 0;
} else {
if (delta < 5000) {
// seek at 10x speed for the first 5 seconds
delta = delta * 10;
} else {
// seek at 40x after that
delta = 50000 + (delta - 5000) * 40;
}
long newpos = mStartSeekPos + delta;
long duration =
getMediaController().getMetadata().getLong(MediaMetadata.METADATA_KEY_DURATION);
if (newpos >= duration) {
// move to next track
getMediaController().getTransportControls().skipToNext();
mStartSeekPos -= duration; // is OK to go negative
newpos -= duration;
}
if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
getMediaController().getTransportControls().seekTo(newpos);
mLastSeekEventTime = delta;
}
updateProgressBar();
}
}
private void toggleShuffle() {
// TODO(b/36371715): Implement shuffle for SHUFFLE_NORMAL, SHUFFLE_AUTO, SHUFFLE_NONE
LogHelper.d(TAG, "Shuffle not implemented yet");
Toast.makeText(this, "Shuffle not implemented yet", Toast.LENGTH_SHORT).show();
}
private void setRepeatMode(MediaPlaybackService.RepeatMode repeatMode) {
Bundle extras = new Bundle();
extras.putInt(MediaPlaybackService.REPEAT_MODE, repeatMode.ordinal());
getMediaController().getTransportControls().sendCustomAction(
MediaPlaybackService.CMD_REPEAT, extras);
}
private void setRepeatButtonImage(MediaPlaybackService.RepeatMode repeatMode) {
if (getMediaController() == null) return;
Bundle extras = getMediaController().getExtras();
if (extras == null) return;
if (repeatMode == null) {
repeatMode = MediaPlaybackService.RepeatMode
.values()[extras.getInt(MediaPlaybackService.REPEAT_MODE)];
}
switch (repeatMode) {
case REPEAT_CURRENT:
mRepeatButton.setImageResource(R.drawable.ic_mp_repeat_once_btn);
break;
case REPEAT_ALL:
mRepeatButton.setImageResource(R.drawable.ic_mp_repeat_all_btn);
break;
case REPEAT_NONE:
default:
mRepeatButton.setImageResource(R.drawable.ic_mp_repeat_off_btn);
break;
}
}
private void showToast(int resid) {
if (mToast == null) {
mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
}
mToast.setText(resid);
mToast.show();
}
private void setShuffleButtonImage() {
if (getMediaController() == null) return;
mShuffleButton.setImageResource(R.drawable.ic_mp_shuffle_off_btn);
}
private void setPauseButtonImage() {
if (getMediaController() == null) {
return;
}
if (getMediaController().getPlaybackState().getState() != PlaybackState.STATE_PLAYING) {
mPlayPauseButton.setImageResource(android.R.drawable.ic_media_play);
} else {
mPlayPauseButton.setImageResource(android.R.drawable.ic_media_pause);
}
}
private long updateProgressBar() {
MediaController mediaController = getMediaController();
if (mediaController == null || mediaController.getMetadata() == null
|| mediaController.getPlaybackState() == null) {
return 500;
}
long duration = mediaController.getMetadata().getLong(MediaMetadata.METADATA_KEY_DURATION);
long pos = mediaController.getPlaybackState().getPosition();
if ((pos >= 0) && (duration > 0)) {
mCurrentTime.setText(MusicUtils.makeTimeString(this, pos / 1000));
int progress = (int) (1000 * pos / duration);
mProgress.setProgress(progress);
if (mediaController.getPlaybackState().getState() == PlaybackState.STATE_PLAYING) {
mCurrentTime.setVisibility(View.VISIBLE);
} else {
// blink the counter
int vis = mCurrentTime.getVisibility();
mCurrentTime.setVisibility(vis == View.INVISIBLE ? View.VISIBLE : View.INVISIBLE);
return 500;
}
} else {
mCurrentTime.setText("--:--");
mProgress.setProgress(1000);
}
// calculate the number of milliseconds until the next full second, so
// the counter can be updated at just the right time
long remaining = 1000 - (pos % 1000);
// approximate how often we would need to refresh the slider to
// move it smoothly
int width = mProgress.getWidth();
if (width == 0) width = 320;
long smoothrefreshtime = duration / width;
if (smoothrefreshtime > remaining) return remaining;
if (smoothrefreshtime < 20) return 20;
return smoothrefreshtime;
}
private void updateTrackInfo() {
LogHelper.d(TAG, "updateTrackInfo()");
if (getMediaController() == null) {
return;
}
MediaMetadata metadata = getMediaController().getMetadata();
if (metadata == null) {
return;
}
mTrackInfo.setVisibility(View.VISIBLE);
mTrackName.setText(metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
LogHelper.d(TAG, "Track Name: ", mTrackName.getText());
String artistName = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
if (artistName.equals(MusicProvider.UNKOWN)) {
artistName = getString(R.string.unknown_artist_name);
}
mArtistName.setText(artistName);
String albumName = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
if (albumName.equals(MusicProvider.UNKOWN)) {
albumName = getString(R.string.unknown_album_name);
}
mAlbumName.setText(albumName);
Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
if (albumArt != null) {
mAlbumArt.setImageBitmap(albumArt);
} else {
mAlbumArt.setImageDrawable(mDefaultAlbumArt);
}
mAlbumArt.setVisibility(View.VISIBLE);
long duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
mTotalTime.setText(MusicUtils.makeTimeString(this, duration / 1000));
}
}