1dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli/* 2dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Copyright (C) 2017 The Android Open Source Project 3dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 4dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Licensed under the Apache License, Version 2.0 (the "License"); 5dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * you may not use this file except in compliance with the License. 6dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * You may obtain a copy of the License at 7dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 8dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * http://www.apache.org/licenses/LICENSE-2.0 9dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 10dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Unless required by applicable law or agreed to in writing, software 11dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * distributed under the License is distributed on an "AS IS" BASIS, 12dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * See the License for the specific language governing permissions and 14dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * limitations under the License. 15dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 16dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.media; 18dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_FAST_FORWARD; 20ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_PLAY_PAUSE; 21ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_REPEAT; 22ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_REWIND; 23ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SHUFFLE; 24ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SKIP_TO_NEXT; 25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SKIP_TO_PREVIOUS; 26dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 27dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.content.Context; 28dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.graphics.Bitmap; 29dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.graphics.drawable.BitmapDrawable; 30dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.graphics.drawable.Drawable; 31dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.os.Handler; 32dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.support.v4.media.MediaMetadataCompat; 3324919ee8c30d91ec056cae6c4f578d7007cbe968Aurimas Liutikasimport android.support.v4.media.session.MediaControllerCompat; 34dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.support.v4.media.session.PlaybackStateCompat; 35dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.util.Log; 36dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 378619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.widget.PlaybackControlsRow; 388619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas 39dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli/** 40dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * A helper class for implementing a adapter layer for {@link MediaControllerCompat}. 41dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 42dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjianglipublic class MediaControllerAdapter extends PlayerAdapter { 43dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 44dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private static final String TAG = "MediaControllerAdapter"; 45dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private static final boolean DEBUG = false; 46dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 47dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private MediaControllerCompat mController; 48dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private Handler mHandler = new Handler(); 49dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 50dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // Runnable object to update current media's playing position. 51dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private final Runnable mPositionUpdaterRunnable = new Runnable() { 52dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 53dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void run() { 54dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onCurrentPositionChanged(MediaControllerAdapter.this); 55dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mHandler.postDelayed(this, getUpdatePeriod()); 56dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 57dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli }; 58dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 59dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // Update period to post runnable. 60dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private int getUpdatePeriod() { 61dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return 16; 62dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 63dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 64dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private boolean mIsBuffering = false; 65dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 66dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli MediaControllerCompat.Callback mMediaControllerCallback = 67dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli new MediaControllerCompat.Callback() { 68dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 69dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void onPlaybackStateChanged(PlaybackStateCompat state) { 70dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mIsBuffering && state.getState() != PlaybackStateCompat.STATE_BUFFERING) { 71dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onBufferingStateChanged(MediaControllerAdapter.this, false); 72dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onBufferedPositionChanged(MediaControllerAdapter.this); 73dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mIsBuffering = false; 74dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 75dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (state.getState() == PlaybackStateCompat.STATE_NONE) { 76dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // The STATE_NONE playback state will only occurs when initialize the player 77dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // at first time. 78dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (DEBUG) { 79dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli Log.d(TAG, "Playback state is none"); 80dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 81dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else if (state.getState() == PlaybackStateCompat.STATE_STOPPED) { 82dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // STATE_STOPPED is associated with onPlayCompleted() callback. 83dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // STATE_STOPPED playback state will only occurs when the last item in 84dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // play list is finished. And repeat mode is not enabled. 85dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onPlayCompleted(MediaControllerAdapter.this); 86dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else if (state.getState() == PlaybackStateCompat.STATE_PAUSED) { 87dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onPlayStateChanged(MediaControllerAdapter.this); 88dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onCurrentPositionChanged(MediaControllerAdapter.this); 89dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else if (state.getState() == PlaybackStateCompat.STATE_PLAYING) { 90dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onPlayStateChanged(MediaControllerAdapter.this); 91dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onCurrentPositionChanged(MediaControllerAdapter.this); 92dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else if (state.getState() == PlaybackStateCompat.STATE_BUFFERING) { 93dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mIsBuffering = true; 94dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onBufferingStateChanged(MediaControllerAdapter.this, true); 95dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onBufferedPositionChanged(MediaControllerAdapter.this); 96dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else if (state.getState() == PlaybackStateCompat.STATE_ERROR) { 97dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli CharSequence errorMessage = state.getErrorMessage(); 98dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (errorMessage == null) { 99dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onError(MediaControllerAdapter.this, state.getErrorCode(), 100dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli ""); 101dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else { 102dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onError(MediaControllerAdapter.this, state.getErrorCode(), 103dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli state.getErrorMessage().toString()); 104dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 105dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else if (state.getState() == PlaybackStateCompat.STATE_FAST_FORWARDING) { 106dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onPlayStateChanged(MediaControllerAdapter.this); 107dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onCurrentPositionChanged(MediaControllerAdapter.this); 108dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } else if (state.getState() == PlaybackStateCompat.STATE_REWINDING) { 109dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onPlayStateChanged(MediaControllerAdapter.this); 110dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onCurrentPositionChanged(MediaControllerAdapter.this); 111dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 112dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 113dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 114dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 115dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void onMetadataChanged(MediaMetadataCompat metadata) { 116dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli getCallback().onMetadataChanged(MediaControllerAdapter.this); 117dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 118dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli }; 119dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 120dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli /** 121dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Constructor for the adapter using {@link MediaControllerCompat}. 122dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 123dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @param controller Object of MediaControllerCompat.. 124dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 125dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public MediaControllerAdapter(MediaControllerCompat controller) { 126dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (controller == null) { 127dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli throw new NullPointerException("Object of MediaControllerCompat is null"); 128dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 129dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController = controller; 130dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 131dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 132dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli /** 133dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Return the object of {@link MediaControllerCompat} from this class. 134dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 135dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @return Media Controller Compat object owned by this class. 136dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 137dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public MediaControllerCompat getMediaController() { 138dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return mController; 139dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 140dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 141dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 142dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void play() { 143dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().play(); 144dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 145dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 146dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 147dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void pause() { 148dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().pause(); 149dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 150dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 151dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 152dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void seekTo(long positionInMs) { 153dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().seekTo(positionInMs); 154dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 155dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 156dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 157dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void next() { 158dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().skipToNext(); 159dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 160dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 161dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 162dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void previous() { 163dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().skipToPrevious(); 164dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 165dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 166dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 167dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void fastForward() { 168dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().fastForward(); 169dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 170dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 171dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 172dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void rewind() { 173dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().rewind(); 174dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 175dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 176dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 177dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void setRepeatAction(int repeatActionIndex) { 178dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli int repeatMode = mapRepeatActionToRepeatMode(repeatActionIndex); 179dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().setRepeatMode(repeatMode); 180dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 181dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 182dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 183dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void setShuffleAction(int shuffleActionIndex) { 184dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli int shuffleMode = mapShuffleActionToShuffleMode(shuffleActionIndex); 185dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.getTransportControls().setShuffleMode(shuffleMode); 186dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 187dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 188dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 189dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public boolean isPlaying() { 190dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getPlaybackState() == null) { 191dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return false; 192dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 193dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return mController.getPlaybackState().getState() 194dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli == PlaybackStateCompat.STATE_PLAYING 195dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli || mController.getPlaybackState().getState() 196dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli == PlaybackStateCompat.STATE_FAST_FORWARDING 197dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli || mController.getPlaybackState().getState() == PlaybackStateCompat.STATE_REWINDING; 198dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 199dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 200dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 201dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public long getCurrentPosition() { 202dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getPlaybackState() == null) { 203dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return 0; 204dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 205dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return mController.getPlaybackState().getPosition(); 206dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 207dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 208dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 209dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public long getBufferedPosition() { 210dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getPlaybackState() == null) { 211dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return 0; 212dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 213dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return mController.getPlaybackState().getBufferedPosition(); 214dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 215dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 216dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli /** 217dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Get current media's title. 218dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 219dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @return Title of current media. 220dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 221dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public CharSequence getMediaTitle() { 222dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getMetadata() == null) { 223dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return ""; 224dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 225dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return mController.getMetadata().getDescription().getTitle(); 226dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 227dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 228dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli /** 229dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Get current media's subtitle. 230dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 231dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @return Subtitle of current media. 232dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 233dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public CharSequence getMediaSubtitle() { 234dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getMetadata() == null) { 235dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return ""; 236dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 237dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return mController.getMetadata().getDescription().getSubtitle(); 238dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 239dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 240dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli /** 241dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Get current media's drawable art. 242dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 243dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @return Drawable art of current media. 244dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 245dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public Drawable getMediaArt(Context context) { 246dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getMetadata() == null) { 247dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return null; 248dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 249dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli Bitmap bitmap = mController.getMetadata().getDescription().getIconBitmap(); 250dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return bitmap == null ? null : new BitmapDrawable(context.getResources(), bitmap); 251dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 252dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 253dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 254dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public long getDuration() { 255dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getMetadata() == null) { 256dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return 0; 257dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 258dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return (int) mController.getMetadata().getLong( 259dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli MediaMetadataCompat.METADATA_KEY_DURATION); 260dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 261dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 262dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 263dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void onAttachedToHost(PlaybackGlueHost host) { 264dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.registerCallback(mMediaControllerCallback); 265dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 266dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 267dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 268dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void onDetachedFromHost() { 269dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mController.unregisterCallback(mMediaControllerCallback); 270dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 271dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 272dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 273dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public void setProgressUpdatingEnabled(boolean enabled) { 274dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mHandler.removeCallbacks(mPositionUpdaterRunnable); 275dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (!enabled) { 276dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return; 277dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 278dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli mHandler.postDelayed(mPositionUpdaterRunnable, getUpdatePeriod()); 279dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 280dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 281dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli @Override 282dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli public long getSupportedActions() { 283dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli long supportedActions = 0; 284dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if (mController.getPlaybackState() == null) { 285dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return supportedActions; 286dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 287dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli long actionsFromController = mController.getPlaybackState().getActions(); 288dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli // Translation. 289dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if ((actionsFromController & PlaybackStateCompat.ACTION_PLAY_PAUSE) != 0) { 290dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli supportedActions |= ACTION_PLAY_PAUSE; 291dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 292dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if ((actionsFromController & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) { 293dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli supportedActions |= ACTION_SKIP_TO_NEXT; 294dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 295dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if ((actionsFromController & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) { 296dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli supportedActions |= ACTION_SKIP_TO_PREVIOUS; 297dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 298dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if ((actionsFromController & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) { 299dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli supportedActions |= ACTION_FAST_FORWARD; 300dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 301dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if ((actionsFromController & PlaybackStateCompat.ACTION_REWIND) != 0) { 302dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli supportedActions |= ACTION_REWIND; 303dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 304dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli if ((actionsFromController & PlaybackStateCompat.ACTION_SET_REPEAT_MODE) != 0) { 305dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli supportedActions |= ACTION_REPEAT; 306dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 307bd2d1474b96d3045aa1048e06d9debced798455bHyundo Moon if ((actionsFromController & PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE) != 0) { 308dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli supportedActions |= ACTION_SHUFFLE; 309dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 310dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return supportedActions; 311dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 312dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 313dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli /** 314dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * This function will translate the index of RepeatAction in PlaybackControlsRow to 315dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * the repeat mode which is defined by PlaybackStateCompat. 316dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 317dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @param repeatActionIndex Index of RepeatAction in PlaybackControlsRow. 318dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @return Repeat Mode in playback state. 319dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 320dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private int mapRepeatActionToRepeatMode(int repeatActionIndex) { 321dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli switch (repeatActionIndex) { 322dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli case PlaybackControlsRow.RepeatAction.INDEX_NONE: 323dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return PlaybackStateCompat.REPEAT_MODE_NONE; 324dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli case PlaybackControlsRow.RepeatAction.INDEX_ALL: 325dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return PlaybackStateCompat.REPEAT_MODE_ALL; 326dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli case PlaybackControlsRow.RepeatAction.INDEX_ONE: 327dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return PlaybackStateCompat.REPEAT_MODE_ONE; 328dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 329dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return -1; 330dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 331dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 332dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli /** 333dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * This function will translate the index of RepeatAction in PlaybackControlsRow to 334dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * the repeat mode which is defined by PlaybackStateCompat. 335dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * 336dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @param shuffleActionIndex Index of RepeatAction in PlaybackControlsRow. 337dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * @return Repeat Mode in playback state. 338dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */ 339dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli private int mapShuffleActionToShuffleMode(int shuffleActionIndex) { 340dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli switch (shuffleActionIndex) { 341dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli case PlaybackControlsRow.ShuffleAction.INDEX_OFF: 342dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return PlaybackStateCompat.SHUFFLE_MODE_NONE; 343dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli case PlaybackControlsRow.ShuffleAction.INDEX_ON: 344dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return PlaybackStateCompat.SHUFFLE_MODE_ALL; 345dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 346dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli return -1; 347dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli } 348dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli} 349dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli 350