| /* |
| * Copyright (C) 2014 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.example.android.musicservicedemo; |
| |
| import android.app.Fragment; |
| import android.content.ComponentName; |
| import android.media.browse.MediaBrowser; |
| import android.media.session.MediaController; |
| import android.media.session.MediaSession; |
| import android.media.session.PlaybackState; |
| import android.os.Bundle; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.AdapterView; |
| import android.widget.ImageButton; |
| import android.widget.ListView; |
| |
| import com.example.android.musicservicedemo.utils.LogHelper; |
| |
| import java.util.List; |
| |
| /** |
| * A class that shows the Media Queue to the user. |
| */ |
| public class QueueFragment extends Fragment { |
| |
| private static final String TAG = QueueFragment.class.getSimpleName(); |
| |
| private ImageButton mSkipNext; |
| private ImageButton mSkipPrevious; |
| private ImageButton mPlayPause; |
| |
| private MediaBrowser mMediaBrowser; |
| private MediaController.TransportControls mTransportControls; |
| private MediaController mMediaController; |
| private PlaybackState mPlaybackState; |
| |
| private QueueAdapter mQueueAdapter; |
| |
| private MediaBrowser.ConnectionCallback mConnectionCallback = |
| new MediaBrowser.ConnectionCallback() { |
| @Override |
| public void onConnected() { |
| LogHelper.d(TAG, "onConnected: session token ", mMediaBrowser.getSessionToken()); |
| |
| if (mMediaBrowser.getSessionToken() == null) { |
| throw new IllegalArgumentException("No Session token"); |
| } |
| |
| mMediaController = new MediaController(getActivity(), |
| mMediaBrowser.getSessionToken()); |
| mTransportControls = mMediaController.getTransportControls(); |
| mMediaController.registerCallback(mSessionCallback); |
| |
| getActivity().setMediaController(mMediaController); |
| mPlaybackState = mMediaController.getPlaybackState(); |
| |
| List<MediaSession.QueueItem> queue = mMediaController.getQueue(); |
| if (queue != null) { |
| mQueueAdapter.clear(); |
| mQueueAdapter.notifyDataSetInvalidated(); |
| mQueueAdapter.addAll(queue); |
| mQueueAdapter.notifyDataSetChanged(); |
| } |
| onPlaybackStateChanged(mPlaybackState); |
| } |
| |
| @Override |
| public void onConnectionFailed() { |
| LogHelper.d(TAG, "onConnectionFailed"); |
| } |
| |
| @Override |
| public void onConnectionSuspended() { |
| LogHelper.d(TAG, "onConnectionSuspended"); |
| mMediaController.unregisterCallback(mSessionCallback); |
| mTransportControls = null; |
| mMediaController = null; |
| getActivity().setMediaController(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 mSessionCallback = 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.getState()); |
| mPlaybackState = state; |
| QueueFragment.this.onPlaybackStateChanged(state); |
| } |
| |
| @Override |
| public void onQueueChanged(List<MediaSession.QueueItem> queue) { |
| LogHelper.d(TAG, "onQueueChanged ", queue); |
| if (queue != null) { |
| mQueueAdapter.clear(); |
| mQueueAdapter.notifyDataSetInvalidated(); |
| mQueueAdapter.addAll(queue); |
| mQueueAdapter.notifyDataSetChanged(); |
| } |
| } |
| }; |
| |
| public static QueueFragment newInstance() { |
| return new QueueFragment(); |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| View rootView = inflater.inflate(R.layout.fragment_list, container, false); |
| |
| mSkipPrevious = (ImageButton) rootView.findViewById(R.id.skip_previous); |
| mSkipPrevious.setEnabled(false); |
| mSkipPrevious.setOnClickListener(mButtonListener); |
| |
| mSkipNext = (ImageButton) rootView.findViewById(R.id.skip_next); |
| mSkipNext.setEnabled(false); |
| mSkipNext.setOnClickListener(mButtonListener); |
| |
| mPlayPause = (ImageButton) rootView.findViewById(R.id.play_pause); |
| mPlayPause.setEnabled(true); |
| mPlayPause.setOnClickListener(mButtonListener); |
| |
| mQueueAdapter = new QueueAdapter(getActivity()); |
| |
| ListView mListView = (ListView) rootView.findViewById(R.id.list_view); |
| mListView.setAdapter(mQueueAdapter); |
| mListView.setFocusable(true); |
| mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { |
| @Override |
| public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
| MediaSession.QueueItem item = mQueueAdapter.getItem(position); |
| mTransportControls.skipToQueueItem(item.getQueueId()); |
| } |
| }); |
| |
| mMediaBrowser = new MediaBrowser(getActivity(), |
| new ComponentName(getActivity(), MusicService.class), |
| mConnectionCallback, null); |
| |
| return rootView; |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| if (mMediaBrowser != null) { |
| mMediaBrowser.connect(); |
| } |
| } |
| |
| @Override |
| public void onPause() { |
| super.onPause(); |
| if (mMediaController != null) { |
| mMediaController.unregisterCallback(mSessionCallback); |
| } |
| if (mMediaBrowser != null) { |
| mMediaBrowser.disconnect(); |
| } |
| } |
| |
| |
| private void onPlaybackStateChanged(PlaybackState state) { |
| LogHelper.d(TAG, "onPlaybackStateChanged ", state); |
| if (state == null) { |
| return; |
| } |
| mQueueAdapter.setActiveQueueItemId(state.getActiveQueueItemId()); |
| mQueueAdapter.notifyDataSetChanged(); |
| boolean enablePlay = false; |
| StringBuilder statusBuilder = new StringBuilder(); |
| switch (state.getState()) { |
| case PlaybackState.STATE_PLAYING: |
| statusBuilder.append("playing"); |
| enablePlay = false; |
| break; |
| case PlaybackState.STATE_PAUSED: |
| statusBuilder.append("paused"); |
| enablePlay = true; |
| break; |
| case PlaybackState.STATE_STOPPED: |
| statusBuilder.append("ended"); |
| enablePlay = true; |
| break; |
| case PlaybackState.STATE_ERROR: |
| statusBuilder.append("error: ").append(state.getErrorMessage()); |
| break; |
| case PlaybackState.STATE_BUFFERING: |
| statusBuilder.append("buffering"); |
| break; |
| case PlaybackState.STATE_NONE: |
| statusBuilder.append("none"); |
| enablePlay = false; |
| break; |
| case PlaybackState.STATE_CONNECTING: |
| statusBuilder.append("connecting"); |
| break; |
| default: |
| statusBuilder.append(mPlaybackState); |
| } |
| statusBuilder.append(" -- At position: ").append(state.getPosition()); |
| LogHelper.d(TAG, statusBuilder.toString()); |
| |
| if (enablePlay) { |
| mPlayPause.setImageDrawable( |
| getActivity().getDrawable(R.drawable.ic_play_arrow_white_24dp)); |
| } else { |
| mPlayPause.setImageDrawable(getActivity().getDrawable(R.drawable.ic_pause_white_24dp)); |
| } |
| |
| mSkipPrevious.setEnabled((state.getActions() & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0); |
| mSkipNext.setEnabled((state.getActions() & PlaybackState.ACTION_SKIP_TO_NEXT) != 0); |
| |
| LogHelper.d(TAG, "Queue From MediaController *** Title " + |
| mMediaController.getQueueTitle() + "\n: Queue: " + mMediaController.getQueue() + |
| "\n Metadata " + mMediaController.getMetadata()); |
| } |
| |
| private View.OnClickListener mButtonListener = new View.OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| final int state = mPlaybackState == null ? |
| PlaybackState.STATE_NONE : mPlaybackState.getState(); |
| switch (v.getId()) { |
| case R.id.play_pause: |
| LogHelper.d(TAG, "Play button pressed, in state " + state); |
| if (state == PlaybackState.STATE_PAUSED || |
| state == PlaybackState.STATE_STOPPED || |
| state == PlaybackState.STATE_NONE) { |
| playMedia(); |
| } else if (state == PlaybackState.STATE_PLAYING) { |
| pauseMedia(); |
| } |
| break; |
| case R.id.skip_previous: |
| LogHelper.d(TAG, "Start button pressed, in state " + state); |
| skipToPrevious(); |
| break; |
| case R.id.skip_next: |
| skipToNext(); |
| break; |
| } |
| } |
| }; |
| |
| private void playMedia() { |
| if (mTransportControls != null) { |
| mTransportControls.play(); |
| } |
| } |
| |
| private void pauseMedia() { |
| if (mTransportControls != null) { |
| mTransportControls.pause(); |
| } |
| } |
| |
| private void skipToPrevious() { |
| if (mTransportControls != null) { |
| mTransportControls.skipToPrevious(); |
| } |
| } |
| |
| private void skipToNext() { |
| if (mTransportControls != null) { |
| mTransportControls.skipToNext(); |
| } |
| } |
| } |