Fields Summary |
---|
private static final int | RESET_TO_METADATA_DELAY |
protected static final boolean | DEBUG |
protected static final String | TAG |
private static final boolean | ANIMATE_TRANSITIONS |
protected static final long | QUIESCENT_PLAYBACK_FACTOR |
private android.view.ViewGroup | mMetadataContainer |
private android.view.ViewGroup | mInfoContainer |
private android.widget.TextView | mTrackTitle |
private android.widget.TextView | mTrackArtistAlbum |
private android.view.View | mTransientSeek |
private android.widget.SeekBar | mTransientSeekBar |
private android.widget.TextView | mTransientSeekTimeElapsed |
private android.widget.TextView | mTransientSeekTimeTotal |
private android.widget.ImageView | mBtnPrev |
private android.widget.ImageView | mBtnPlay |
private android.widget.ImageView | mBtnNext |
private Metadata | mMetadata |
private int | mTransportControlFlags |
private int | mCurrentPlayState |
private android.media.AudioManager | mAudioManager |
private android.media.RemoteController | mRemoteController |
private android.widget.ImageView | mBadge |
private boolean | mSeekEnabled |
private DateFormat | mFormat |
private Date | mTempDate |
private RemoteController.MetadataEditor | mPopulateMetadataWhenAttachedThe metadata which should be populated into the view once we've been attached |
private RemoteController.OnClientUpdateListener | mRCClientUpdateListener |
private final UpdateSeekBarRunnable | mUpdateSeekBars |
private final Runnable | mResetToMetadata |
private final OnClickListener | mTransportCommandListener |
private final OnLongClickListener | mTransportShowSeekBarListener |
private final FutureSeekRunnable | mFutureSeekRunnable |
private final SeekBar.OnSeekBarChangeListener | mOnSeekBarChangeListener |
private static final int | TRANSITION_DURATION |
private final android.transition.TransitionSet | mMetadataChangeTransition |
KeyguardHostView.TransportControlCallback | mTransportControlCallback |
private final KeyguardUpdateMonitorCallback | mUpdateMonitor |
Methods Summary |
---|
void | cancelResetToMetadata()
removeCallbacks(mResetToMetadata);
|
void | clearMetadata()
mPopulateMetadataWhenAttached = null;
mMetadata.clear();
populateMetadata();
|
void | delayResetToMetadata()
removeCallbacks(mResetToMetadata);
postDelayed(mResetToMetadata, RESET_TO_METADATA_DELAY);
|
public void | onAttachedToWindow()
super.onAttachedToWindow();
if (DEBUG) Log.v(TAG, "onAttachToWindow()");
if (mPopulateMetadataWhenAttached != null) {
updateMetadata(mPopulateMetadataWhenAttached);
mPopulateMetadataWhenAttached = null;
}
if (DEBUG) Log.v(TAG, "Registering TCV " + this);
mMetadata.clear();
mAudioManager.registerRemoteController(mRemoteController);
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitor);
|
protected void | onConfigurationChanged(android.content.res.Configuration newConfig)
super.onConfigurationChanged(newConfig);
final DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
final int dim = Math.max(dm.widthPixels, dm.heightPixels);
mRemoteController.setArtworkConfiguration(true, dim, dim);
|
public void | onDetachedFromWindow()
if (DEBUG) Log.v(TAG, "onDetachFromWindow()");
super.onDetachedFromWindow();
if (DEBUG) Log.v(TAG, "Unregistering TCV " + this);
mAudioManager.unregisterRemoteController(mRemoteController);
KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor);
mMetadata.clear();
removeCallbacks(mUpdateSeekBars);
|
public void | onFinishInflate()
super.onFinishInflate();
mInfoContainer = (ViewGroup) findViewById(R.id.info_container);
mMetadataContainer = (ViewGroup) findViewById(R.id.metadata_container);
mBadge = (ImageView) findViewById(R.id.badge);
mTrackTitle = (TextView) findViewById(R.id.title);
mTrackArtistAlbum = (TextView) findViewById(R.id.artist_album);
mTransientSeek = findViewById(R.id.transient_seek);
mTransientSeekBar = (SeekBar) findViewById(R.id.transient_seek_bar);
mTransientSeekBar.setOnSeekBarChangeListener(mOnSeekBarChangeListener);
mTransientSeekTimeElapsed = (TextView) findViewById(R.id.transient_seek_time_elapsed);
mTransientSeekTimeTotal = (TextView) findViewById(R.id.transient_seek_time_remaining);
mBtnPrev = (ImageView) findViewById(R.id.btn_prev);
mBtnPlay = (ImageView) findViewById(R.id.btn_play);
mBtnNext = (ImageView) findViewById(R.id.btn_next);
final View buttons[] = { mBtnPrev, mBtnPlay, mBtnNext };
for (View view : buttons) {
view.setOnClickListener(mTransportCommandListener);
view.setOnLongClickListener(mTransportShowSeekBarListener);
}
final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
setEnableMarquee(screenOn);
// Allow long-press anywhere else in this view to show the seek bar
setOnLongClickListener(mTransportShowSeekBarListener);
|
protected void | onRestoreInstanceState(android.os.Parcelable state)
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mMetadata.artist = ss.artist;
mMetadata.trackTitle = ss.trackTitle;
mMetadata.albumTitle = ss.albumTitle;
mMetadata.duration = ss.duration;
mMetadata.bitmap = ss.bitmap;
populateMetadata();
|
protected android.os.Parcelable | onSaveInstanceState()
SavedState ss = new SavedState(super.onSaveInstanceState());
ss.artist = mMetadata.artist;
ss.trackTitle = mMetadata.trackTitle;
ss.albumTitle = mMetadata.albumTitle;
ss.duration = mMetadata.duration;
ss.bitmap = mMetadata.bitmap;
return ss;
|
private static final boolean | playbackPositionShouldMove(int playstate)
switch(playstate) {
case RemoteControlClient.PLAYSTATE_STOPPED:
case RemoteControlClient.PLAYSTATE_PAUSED:
case RemoteControlClient.PLAYSTATE_BUFFERING:
case RemoteControlClient.PLAYSTATE_ERROR:
case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
return false;
case RemoteControlClient.PLAYSTATE_PLAYING:
case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
case RemoteControlClient.PLAYSTATE_REWINDING:
default:
return true;
}
|
private void | populateMetadata()Populates the given metadata into the view
if (ANIMATE_TRANSITIONS && isLaidOut() && mMetadataContainer.getVisibility() == VISIBLE) {
TransitionManager.beginDelayedTransition(mMetadataContainer, mMetadataChangeTransition);
}
final String remoteClientPackage = mRemoteController.getRemoteControlClientPackageName();
Drawable badgeIcon = null;
try {
badgeIcon = getContext().getPackageManager().getApplicationIcon(remoteClientPackage);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Couldn't get remote control client package icon", e);
}
setBadgeIcon(badgeIcon);
mTrackTitle.setText(!TextUtils.isEmpty(mMetadata.trackTitle)
? mMetadata.trackTitle : null);
final StringBuilder sb = new StringBuilder();
if (!TextUtils.isEmpty(mMetadata.artist)) {
if (sb.length() != 0) {
sb.append(" - ");
}
sb.append(mMetadata.artist);
}
if (!TextUtils.isEmpty(mMetadata.albumTitle)) {
if (sb.length() != 0) {
sb.append(" - ");
}
sb.append(mMetadata.albumTitle);
}
final String trackArtistAlbum = sb.toString();
mTrackArtistAlbum.setText(!TextUtils.isEmpty(trackArtistAlbum) ?
trackArtistAlbum : null);
if (mMetadata.duration >= 0) {
setSeekBarsEnabled(true);
setSeekBarDuration(mMetadata.duration);
final String skeleton;
if (mMetadata.duration >= 86400000) {
skeleton = "DDD kk mm ss";
} else if (mMetadata.duration >= 3600000) {
skeleton = "kk mm ss";
} else {
skeleton = "mm ss";
}
mFormat = new SimpleDateFormat(DateFormat.getBestDateTimePattern(
getContext().getResources().getConfiguration().locale,
skeleton));
mFormat.setTimeZone(TimeZone.getTimeZone("GMT+0"));
} else {
setSeekBarsEnabled(false);
}
KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(mMetadata.bitmap);
final int flags = mTransportControlFlags;
setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
setVisibilityBasedOnFlag(mBtnPlay, flags,
RemoteControlClient.FLAG_KEY_MEDIA_PLAY
| RemoteControlClient.FLAG_KEY_MEDIA_PAUSE
| RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
| RemoteControlClient.FLAG_KEY_MEDIA_STOP);
updatePlayPauseState(mCurrentPlayState);
|
public boolean | providesClock()
return false;
|
void | resetToMetadata()
if (ANIMATE_TRANSITIONS) {
TransitionManager.beginDelayedTransition(mInfoContainer);
}
if (mTransientSeek.getVisibility() == VISIBLE) {
mTransientSeek.setVisibility(INVISIBLE);
mMetadataContainer.setVisibility(VISIBLE);
}
// TODO Also hide ratings, if applicable
|
void | scrubTo(int progress)
mRemoteController.seekTo(progress);
mTransportControlCallback.userActivity();
|
private void | sendMediaButtonClick(int keyCode)
// TODO We should think about sending these up/down events accurately with touch up/down
// on the buttons, but in the near term this will interfere with the long press behavior.
mRemoteController.sendMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
mRemoteController.sendMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
mTransportControlCallback.userActivity();
|
void | setBadgeIcon(android.graphics.drawable.Drawable bmp)
mBadge.setImageDrawable(bmp);
final ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
mBadge.setColorFilter(new ColorMatrixColorFilter(cm));
mBadge.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
mBadge.setImageAlpha(0xef);
|
private void | setEnableMarquee(boolean enabled)
if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee");
if (mTrackTitle != null) mTrackTitle.setSelected(enabled);
if (mTrackArtistAlbum != null) mTrackTitle.setSelected(enabled);
|
void | setSeekBarDuration(long duration)
mTransientSeekBar.setMax((int) duration);
|
void | setSeekBarsEnabled(boolean enabled)
if (enabled == mSeekEnabled) return;
mSeekEnabled = enabled;
if (mTransientSeek.getVisibility() == VISIBLE && !enabled) {
mTransientSeek.setVisibility(INVISIBLE);
mMetadataContainer.setVisibility(VISIBLE);
cancelResetToMetadata();
}
|
public void | setTransportControlCallback(KeyguardHostView.TransportControlCallback transportControlCallback)
mTransportControlCallback = transportControlCallback;
|
private static void | setVisibilityBasedOnFlag(android.view.View view, int flags, int flag)
if ((flags & flag) != 0) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.INVISIBLE);
}
|
boolean | tryToggleSeekBar()
if (ANIMATE_TRANSITIONS) {
TransitionManager.beginDelayedTransition(mInfoContainer);
}
if (mTransientSeek.getVisibility() == VISIBLE) {
mTransientSeek.setVisibility(INVISIBLE);
mMetadataContainer.setVisibility(VISIBLE);
cancelResetToMetadata();
removeCallbacks(mUpdateSeekBars); // don't update if scrubber isn't visible
} else {
mTransientSeek.setVisibility(VISIBLE);
mMetadataContainer.setVisibility(INVISIBLE);
delayResetToMetadata();
if (playbackPositionShouldMove(mCurrentPlayState)) {
mUpdateSeekBars.run();
} else {
mUpdateSeekBars.updateOnce();
}
}
mTransportControlCallback.userActivity();
return true;
|
void | updateMetadata(RemoteController.MetadataEditor data)
if (isAttachedToWindow()) {
mMetadata.artist = data.getString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST,
mMetadata.artist);
mMetadata.trackTitle = data.getString(MediaMetadataRetriever.METADATA_KEY_TITLE,
mMetadata.trackTitle);
mMetadata.albumTitle = data.getString(MediaMetadataRetriever.METADATA_KEY_ALBUM,
mMetadata.albumTitle);
mMetadata.duration = data.getLong(MediaMetadataRetriever.METADATA_KEY_DURATION, -1);
mMetadata.bitmap = data.getBitmap(MediaMetadataEditor.BITMAP_KEY_ARTWORK,
mMetadata.bitmap);
populateMetadata();
} else {
mPopulateMetadataWhenAttached = data;
}
|
private void | updatePlayPauseState(int state)
if (DEBUG) Log.v(TAG,
"updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state);
if (state == mCurrentPlayState) {
return;
}
final int imageResId;
final int imageDescId;
switch (state) {
case RemoteControlClient.PLAYSTATE_ERROR:
imageResId = R.drawable.stat_sys_warning;
// TODO use more specific image description string for warning, but here the "play"
// message is still valid because this button triggers a play command.
imageDescId = R.string.keyguard_transport_play_description;
break;
case RemoteControlClient.PLAYSTATE_PLAYING:
imageResId = R.drawable.ic_media_pause;
imageDescId = R.string.keyguard_transport_pause_description;
break;
case RemoteControlClient.PLAYSTATE_BUFFERING:
imageResId = R.drawable.ic_media_stop;
imageDescId = R.string.keyguard_transport_stop_description;
break;
case RemoteControlClient.PLAYSTATE_PAUSED:
default:
imageResId = R.drawable.ic_media_play;
imageDescId = R.string.keyguard_transport_play_description;
break;
}
boolean clientSupportsSeek = mMetadata != null && mMetadata.duration > 0;
setSeekBarsEnabled(clientSupportsSeek);
mBtnPlay.setImageResource(imageResId);
mBtnPlay.setContentDescription(getResources().getString(imageDescId));
mCurrentPlayState = state;
|
boolean | updateSeekBars()
final int position = (int) mRemoteController.getEstimatedMediaPosition();
if (DEBUG) Log.v(TAG, "Estimated time:" + position);
if (position >= 0) {
mTransientSeekBar.setProgress(position);
return true;
}
Log.w(TAG, "Updating seek bars; received invalid estimated media position (" +
position + "). Disabling seek.");
setSeekBarsEnabled(false);
return false;
|
void | updateSeekDisplay()
if (mMetadata != null && mRemoteController != null && mFormat != null) {
mTempDate.setTime(mRemoteController.getEstimatedMediaPosition());
mTransientSeekTimeElapsed.setText(mFormat.format(mTempDate));
mTempDate.setTime(mMetadata.duration);
mTransientSeekTimeTotal.setText(mFormat.format(mTempDate));
if (DEBUG) Log.d(TAG, "updateSeekDisplay timeElapsed=" + mTempDate +
" duration=" + mMetadata.duration);
}
|
private void | updateTransportControls(int transportControlFlags)
mTransportControlFlags = transportControlFlags;
setSeekBarsEnabled(
(transportControlFlags & RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE) != 0);
|