package com.markzhai.lyrichere.ui; import android.content.ComponentName; import android.media.session.PlaybackState; import android.os.Bundle; import android.os.RemoteException; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.browse.MediaBrowserCompat; import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import android.view.View; import com.markzhai.lyrichere.MusicService; import com.markzhai.lyrichere.R; import com.markzhai.lyrichere.utils.LogUtils; import com.markzhai.lyrichere.utils.NetworkHelper; import java.util.List; /** * Base activity for activities that need to show a playback control fragment when media is playing. */ public abstract class PlaybackControlBaseActivity extends ActionBarCastActivity implements MediaBrowserProvider, MediaControllerProvider { private static final String TAG = LogUtils.makeLogTag("PlaybackControlBaseActivity"); private MediaBrowserCompat mMediaBrowser; private PlaybackControlsFragment mControlsFragment; private MediaControllerCompat mMediaController; private View mControlsContainer; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Connect a media browser just to get the media session token. There are other ways // this can be done, for example by sharing the session token directly. mMediaBrowser = new MediaBrowserCompat(this, new ComponentName(this, MusicService.class), mMediaBrowserConnectionCallback, null); } @Override protected void onStart() { super.onStart(); mControlsContainer = findViewById(R.id.controls_container); mControlsFragment = (PlaybackControlsFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_playback_controls); if (mControlsFragment == null) { throw new IllegalStateException("Missing fragment with id 'fragment_playback_controls'"); } hidePlaybackControls(); if (mMediaBrowser != null) { mMediaBrowser.connect(); } } @Override protected void onStop() { super.onStop(); LogUtils.d(TAG, "Activity onStop"); if (mMediaController != null) { mMediaController.unregisterCallback(mMediaControllerCallback); } if (mMediaBrowser != null) { mMediaBrowser.disconnect(); } } @Override public MediaBrowserCompat getMediaBrowser() { return mMediaBrowser; } @Override public MediaControllerCompat getSupportMediaController() { return mMediaController; } protected void onMediaControllerConnected() { // empty implementation, can be overridden by clients. } protected void showPlaybackControls() { LogUtils.d(TAG, "showPlaybackControls"); if (NetworkHelper.isOnline(this)) { // TODO support animation // getFragmentManager().beginTransaction() // .setCustomAnimations( // R.animator.slide_in_from_bottom, R.animator.slide_out_to_bottom, // R.animator.slide_in_from_bottom, R.animator.slide_out_to_bottom) // .show(mControlsFragment) // .commit(); mControlsContainer.setVisibility(View.VISIBLE); } } protected void hidePlaybackControls() { LogUtils.d(TAG, "hidePlaybackControls"); // TODO support //getFragmentManager().beginTransaction() // .hide(mControlsFragment) // .commit(); mControlsContainer.setVisibility(View.GONE); } /** * Check if the MediaSession is active and in a "playback-able" state * (not NONE and not STOPPED). * * @return true if the MediaSession's state requires playback controls to be visible. */ protected boolean shouldShowControls() { MediaControllerCompat mediaController = mMediaController; if (mediaController == null || mediaController.getMetadata() == null || mediaController.getPlaybackState() == null) { return false; } switch (mediaController.getPlaybackState().getState()) { case PlaybackState.STATE_ERROR: case PlaybackState.STATE_NONE: case PlaybackState.STATE_STOPPED: return false; default: return true; } } private void connectToSession(MediaSessionCompat.Token token) { try { LogUtils.d(TAG, "Session Token: " + token); mMediaController = new MediaControllerCompat(this, token); mMediaController.registerCallback(mMediaControllerCallback); if (shouldShowControls()) { showPlaybackControls(); } else { LogUtils.d(TAG, "connectionCallback.onConnected: " + "hiding controls because metadata is null"); hidePlaybackControls(); } if (mControlsFragment != null) { mControlsFragment.onConnected(); } onMediaControllerConnected(); } catch (RemoteException ex) { LogUtils.e(TAG, ex.getMessage()); } } // Callback that ensures that we are showing the controls private final MediaControllerCompat.Callback mMediaControllerCallback = new MediaControllerCompat.Callback() { @Override public void onSessionDestroyed() { super.onSessionDestroyed(); LogUtils.d(TAG, "onSessionDestroyed"); } @Override public void onSessionEvent(String event, Bundle extras) { super.onSessionEvent(event, extras); LogUtils.d(TAG, "onSessionEvent"); } @Override public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) { super.onQueueChanged(queue); LogUtils.d(TAG, "onQueueChanged"); } @Override public void onQueueTitleChanged(CharSequence title) { super.onQueueTitleChanged(title); LogUtils.d(TAG, "onQueueTitleChanged"); } @Override public void onExtrasChanged(Bundle extras) { super.onExtrasChanged(extras); LogUtils.d(TAG, "onExtrasChanged"); } @Override public void onAudioInfoChanged(MediaControllerCompat.PlaybackInfo info) { super.onAudioInfoChanged(info); LogUtils.d(TAG, "onAudioInfoChanged"); } @Override public void binderDied() { super.binderDied(); LogUtils.d(TAG, "binderDied"); } @Override public void onPlaybackStateChanged(PlaybackStateCompat state) { if (shouldShowControls()) { showPlaybackControls(); } else { LogUtils.d(TAG, "mediaControllerCallback.onPlaybackStateChanged: " + "hiding controls because state is ", state == null ? "null" : state.getState()); hidePlaybackControls(); } } @Override public void onMetadataChanged(MediaMetadataCompat metadata) { if (shouldShowControls()) { showPlaybackControls(); } else { LogUtils.d(TAG, "mediaControllerCallback.onMetadataChanged: " + "hiding controls because metadata is null"); hidePlaybackControls(); } } }; private MediaBrowserCompat.ConnectionCallback mMediaBrowserConnectionCallback = new MediaBrowserCompat.ConnectionCallback() { @Override public void onConnectionSuspended() { super.onConnectionSuspended(); LogUtils.d(TAG, "onConnectionSuspended"); } @Override public void onConnectionFailed() { super.onConnectionFailed(); LogUtils.d(TAG, "onConnectionSuspended"); } @Override public void onConnected() { LogUtils.d(TAG, "onConnected"); MediaSessionCompat.Token token = mMediaBrowser.getSessionToken(); if (token == null) { throw new IllegalArgumentException("No Session token"); } connectToSession(token); } }; }