Home | History | Annotate | Download | only in com.example.android.mediabrowserservice
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.example.android.mediabrowserservice;
     17 
     18 import android.app.Fragment;
     19 import android.content.ComponentName;
     20 import android.media.browse.MediaBrowser;
     21 import android.media.session.MediaController;
     22 import android.media.session.MediaSession;
     23 import android.media.session.PlaybackState;
     24 import android.os.Bundle;
     25 import android.view.LayoutInflater;
     26 import android.view.View;
     27 import android.view.ViewGroup;
     28 import android.widget.AdapterView;
     29 import android.widget.ImageButton;
     30 import android.widget.ListView;
     31 
     32 import com.example.android.mediabrowserservice.utils.LogHelper;
     33 
     34 import java.util.List;
     35 
     36 /**
     37  * A class that shows the Media Queue to the user.
     38  */
     39 public class QueueFragment extends Fragment {
     40 
     41     private static final String TAG = QueueFragment.class.getSimpleName();
     42 
     43     private ImageButton mSkipNext;
     44     private ImageButton mSkipPrevious;
     45     private ImageButton mPlayPause;
     46 
     47     private MediaBrowser mMediaBrowser;
     48     private MediaController.TransportControls mTransportControls;
     49     private MediaController mMediaController;
     50     private PlaybackState mPlaybackState;
     51 
     52     private QueueAdapter mQueueAdapter;
     53 
     54     private MediaBrowser.ConnectionCallback mConnectionCallback =
     55             new MediaBrowser.ConnectionCallback() {
     56         @Override
     57         public void onConnected() {
     58             LogHelper.d(TAG, "onConnected: session token ", mMediaBrowser.getSessionToken());
     59 
     60             if (mMediaBrowser.getSessionToken() == null) {
     61                 throw new IllegalArgumentException("No Session token");
     62             }
     63 
     64             mMediaController = new MediaController(getActivity(),
     65                     mMediaBrowser.getSessionToken());
     66             mTransportControls = mMediaController.getTransportControls();
     67             mMediaController.registerCallback(mSessionCallback);
     68 
     69             getActivity().setMediaController(mMediaController);
     70             mPlaybackState = mMediaController.getPlaybackState();
     71 
     72             List<MediaSession.QueueItem> queue = mMediaController.getQueue();
     73             if (queue != null) {
     74                 mQueueAdapter.clear();
     75                 mQueueAdapter.notifyDataSetInvalidated();
     76                 mQueueAdapter.addAll(queue);
     77                 mQueueAdapter.notifyDataSetChanged();
     78             }
     79             onPlaybackStateChanged(mPlaybackState);
     80         }
     81 
     82         @Override
     83         public void onConnectionFailed() {
     84             LogHelper.d(TAG, "onConnectionFailed");
     85         }
     86 
     87         @Override
     88         public void onConnectionSuspended() {
     89             LogHelper.d(TAG, "onConnectionSuspended");
     90             mMediaController.unregisterCallback(mSessionCallback);
     91             mTransportControls = null;
     92             mMediaController = null;
     93             getActivity().setMediaController(null);
     94         }
     95     };
     96 
     97     // Receive callbacks from the MediaController. Here we update our state such as which queue
     98     // is being shown, the current title and description and the PlaybackState.
     99     private MediaController.Callback mSessionCallback = new MediaController.Callback() {
    100 
    101         @Override
    102         public void onSessionDestroyed() {
    103             LogHelper.d(TAG, "Session destroyed. Need to fetch a new Media Session");
    104         }
    105 
    106         @Override
    107         public void onPlaybackStateChanged(PlaybackState state) {
    108             if (state == null) {
    109                 return;
    110             }
    111             LogHelper.d(TAG, "Received playback state change to state ", state.getState());
    112             mPlaybackState = state;
    113             QueueFragment.this.onPlaybackStateChanged(state);
    114         }
    115 
    116         @Override
    117         public void onQueueChanged(List<MediaSession.QueueItem> queue) {
    118             LogHelper.d(TAG, "onQueueChanged ", queue);
    119             if (queue != null) {
    120                 mQueueAdapter.clear();
    121                 mQueueAdapter.notifyDataSetInvalidated();
    122                 mQueueAdapter.addAll(queue);
    123                 mQueueAdapter.notifyDataSetChanged();
    124             }
    125         }
    126     };
    127 
    128     public static QueueFragment newInstance() {
    129         return new QueueFragment();
    130     }
    131 
    132     @Override
    133     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    134                              Bundle savedInstanceState) {
    135         View rootView = inflater.inflate(R.layout.fragment_list, container, false);
    136 
    137         mSkipPrevious = (ImageButton) rootView.findViewById(R.id.skip_previous);
    138         mSkipPrevious.setEnabled(false);
    139         mSkipPrevious.setOnClickListener(mButtonListener);
    140 
    141         mSkipNext = (ImageButton) rootView.findViewById(R.id.skip_next);
    142         mSkipNext.setEnabled(false);
    143         mSkipNext.setOnClickListener(mButtonListener);
    144 
    145         mPlayPause = (ImageButton) rootView.findViewById(R.id.play_pause);
    146         mPlayPause.setEnabled(true);
    147         mPlayPause.setOnClickListener(mButtonListener);
    148 
    149         mQueueAdapter = new QueueAdapter(getActivity());
    150 
    151         ListView mListView = (ListView) rootView.findViewById(R.id.list_view);
    152         mListView.setAdapter(mQueueAdapter);
    153         mListView.setFocusable(true);
    154         mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    155             @Override
    156             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    157                 MediaSession.QueueItem item = mQueueAdapter.getItem(position);
    158                 mTransportControls.skipToQueueItem(item.getQueueId());
    159             }
    160         });
    161 
    162         mMediaBrowser = new MediaBrowser(getActivity(),
    163                 new ComponentName(getActivity(), MusicService.class),
    164                 mConnectionCallback, null);
    165 
    166         return rootView;
    167     }
    168 
    169     @Override
    170     public void onResume() {
    171         super.onResume();
    172         if (mMediaBrowser != null) {
    173             mMediaBrowser.connect();
    174         }
    175     }
    176 
    177     @Override
    178     public void onPause() {
    179         super.onPause();
    180         if (mMediaController != null) {
    181             mMediaController.unregisterCallback(mSessionCallback);
    182         }
    183         if (mMediaBrowser != null) {
    184             mMediaBrowser.disconnect();
    185         }
    186     }
    187 
    188 
    189     private void onPlaybackStateChanged(PlaybackState state) {
    190         LogHelper.d(TAG, "onPlaybackStateChanged ", state);
    191         if (state == null) {
    192             return;
    193         }
    194         mQueueAdapter.setActiveQueueItemId(state.getActiveQueueItemId());
    195         mQueueAdapter.notifyDataSetChanged();
    196         boolean enablePlay = false;
    197         StringBuilder statusBuilder = new StringBuilder();
    198         switch (state.getState()) {
    199             case PlaybackState.STATE_PLAYING:
    200                 statusBuilder.append("playing");
    201                 enablePlay = false;
    202                 break;
    203             case PlaybackState.STATE_PAUSED:
    204                 statusBuilder.append("paused");
    205                 enablePlay = true;
    206                 break;
    207             case PlaybackState.STATE_STOPPED:
    208                 statusBuilder.append("ended");
    209                 enablePlay = true;
    210                 break;
    211             case PlaybackState.STATE_ERROR:
    212                 statusBuilder.append("error: ").append(state.getErrorMessage());
    213                 break;
    214             case PlaybackState.STATE_BUFFERING:
    215                 statusBuilder.append("buffering");
    216                 break;
    217             case PlaybackState.STATE_NONE:
    218                 statusBuilder.append("none");
    219                 enablePlay = false;
    220                 break;
    221             case PlaybackState.STATE_CONNECTING:
    222                 statusBuilder.append("connecting");
    223                 break;
    224             default:
    225                 statusBuilder.append(mPlaybackState);
    226         }
    227         statusBuilder.append(" -- At position: ").append(state.getPosition());
    228         LogHelper.d(TAG, statusBuilder.toString());
    229 
    230         if (enablePlay) {
    231             mPlayPause.setImageDrawable(
    232                     getActivity().getDrawable(R.drawable.ic_play_arrow_white_24dp));
    233         } else {
    234             mPlayPause.setImageDrawable(getActivity().getDrawable(R.drawable.ic_pause_white_24dp));
    235         }
    236 
    237         mSkipPrevious.setEnabled((state.getActions() & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0);
    238         mSkipNext.setEnabled((state.getActions() & PlaybackState.ACTION_SKIP_TO_NEXT) != 0);
    239 
    240         LogHelper.d(TAG, "Queue From MediaController *** Title " +
    241                 mMediaController.getQueueTitle() + "\n: Queue: " + mMediaController.getQueue() +
    242                 "\n Metadata " + mMediaController.getMetadata());
    243     }
    244 
    245     private View.OnClickListener mButtonListener = new View.OnClickListener() {
    246         @Override
    247         public void onClick(View v) {
    248             final int state = mPlaybackState == null ?
    249                     PlaybackState.STATE_NONE : mPlaybackState.getState();
    250             switch (v.getId()) {
    251                 case R.id.play_pause:
    252                     LogHelper.d(TAG, "Play button pressed, in state " + state);
    253                     if (state == PlaybackState.STATE_PAUSED ||
    254                             state == PlaybackState.STATE_STOPPED ||
    255                             state == PlaybackState.STATE_NONE) {
    256                         playMedia();
    257                     } else if (state == PlaybackState.STATE_PLAYING) {
    258                         pauseMedia();
    259                     }
    260                     break;
    261                 case R.id.skip_previous:
    262                     LogHelper.d(TAG, "Start button pressed, in state " + state);
    263                     skipToPrevious();
    264                     break;
    265                 case R.id.skip_next:
    266                     skipToNext();
    267                     break;
    268             }
    269         }
    270     };
    271 
    272     private void playMedia() {
    273         if (mTransportControls != null) {
    274             mTransportControls.play();
    275         }
    276     }
    277 
    278     private void pauseMedia() {
    279         if (mTransportControls != null) {
    280             mTransportControls.pause();
    281         }
    282     }
    283 
    284     private void skipToPrevious() {
    285         if (mTransportControls != null) {
    286             mTransportControls.skipToPrevious();
    287         }
    288     }
    289 
    290     private void skipToNext() {
    291         if (mTransportControls != null) {
    292             mTransportControls.skipToNext();
    293         }
    294     }
    295 }
    296