MusicConsumptionExampleFragment.java revision 1dd934eb3d2aa4e685585fa0f26c738feee0db4c
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15package android.support.v17.leanback.supportleanbackshowcase.app.media;
16
17import android.content.Context;
18import android.content.res.Resources;
19import android.graphics.drawable.Drawable;
20import android.net.Uri;
21import android.os.Bundle;
22import android.support.v17.leanback.app.PlaybackOverlayFragment;
23import android.support.v17.leanback.supportleanbackshowcase.utils.Constants;
24import android.support.v17.leanback.supportleanbackshowcase.R;
25import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
26import android.support.v17.leanback.supportleanbackshowcase.models.Song;
27import android.support.v17.leanback.supportleanbackshowcase.models.SongList;
28import android.support.v17.leanback.widget.*;
29import android.support.v17.leanback.widget.AbstractMediaItemPresenter;
30import android.util.Log;
31
32import com.google.gson.Gson;
33
34import java.util.List;
35
36/**
37 * This example shows how to play music files and build a simple track list.
38 */
39public class MusicConsumptionExampleFragment extends PlaybackOverlayFragment implements
40        BaseOnItemViewClickedListener, BaseOnItemViewSelectedListener,
41        MediaPlayerGlue.OnMediaFileFinishedPlayingListener {
42
43    private static final String TAG = "MusicConsumptionExampleFragment";
44    private static final int PLAYLIST_ACTION_ID = 0;
45    private static final int FAVORITE_ACTION_ID = 1;
46    private ArrayObjectAdapter mRowsAdapter;
47    private MediaPlayerGlue mGlue;
48    private int mCurrentSongIndex = 0;
49    private List<Song> mSongList;
50    private boolean mAdapterNotified = false;
51
52    @Override public void onCreate(Bundle savedInstanceState) {
53        super.onCreate(savedInstanceState);
54        if (Constants.LOCAL_LOGD) Log.d(TAG, "onCreate");
55
56        mGlue = new MediaPlayerGlue(getActivity(), this) {
57
58            @Override protected void onRowChanged(PlaybackControlsRow row) {
59                if (mRowsAdapter == null || mAdapterNotified) return;
60                //mAdapterNotified = true;
61                mRowsAdapter.notifyArrayItemRangeChanged(0, 1);
62            }
63        };
64        mGlue.setOnMediaFileFinishedPlayingListener(this);
65
66        String json = Utils.inputStreamToString(
67                getResources().openRawResource(R.raw.music_consumption_example));
68
69
70        mSongList = new Gson().fromJson(json, SongList.class).getSongs();
71
72        Resources res = getActivity().getResources();
73
74        // For each song add a playlist and favorite actions.
75        for(Song song : mSongList) {
76            MultiActionsProvider.MultiAction[] mediaRowActions = new
77                    MultiActionsProvider.MultiAction[2];
78            MultiActionsProvider.MultiAction playlistAction = new
79                    MultiActionsProvider.MultiAction(PLAYLIST_ACTION_ID);
80            Drawable[] playlistActionDrawables = new Drawable[] {
81                    res.getDrawable(R.drawable.ic_playlist_add_white_24dp,
82                            getActivity().getTheme()),
83                    res.getDrawable(R.drawable.ic_playlist_add_filled_24dp,
84                            getActivity().getTheme())};
85            playlistAction.setDrawables(playlistActionDrawables);
86            mediaRowActions[0] = playlistAction;
87
88            MultiActionsProvider.MultiAction favoriteAction = new
89                    MultiActionsProvider.MultiAction(FAVORITE_ACTION_ID);
90            Drawable[] favoriteActionDrawables = new Drawable[] {
91                    res.getDrawable(R.drawable.ic_favorite_border_white_24dp,
92                            getActivity().getTheme()),
93                    res.getDrawable(R.drawable.ic_favorite_filled_24dp,
94                            getActivity().getTheme())};
95            favoriteAction.setDrawables(favoriteActionDrawables);
96            mediaRowActions[1] = favoriteAction;
97            song.setMediaRowActions(mediaRowActions);
98        }
99
100        Song song = mSongList.get(mCurrentSongIndex);
101        MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData();
102        metaData.setArtist(song.getDescription());
103        metaData.setTitle(song.getTitle());
104        metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null));
105        Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity()));
106        mGlue.setMetaData(metaData);
107        mGlue.setMediaSource(uri);
108
109        addPlaybackControlsRow();
110    }
111
112    @Override public void onStart() {
113        super.onStart();
114        mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying());
115    }
116
117    @Override public void onStop() {
118        super.onStop();
119        mGlue.enableProgressUpdating(false);
120        mGlue.reset();
121    }
122
123    static class SongPresenter extends AbstractMediaItemPresenter {
124
125        SongPresenter() {
126            super();
127        }
128
129        SongPresenter(Context context, int themeResId) {
130            super(themeResId);
131            setHasMediaRowSeparator(true);
132        }
133
134        @Override
135        protected void onBindMediaDetails(ViewHolder vh, Object item) {
136
137            int favoriteTextColor =  vh.view.getContext().getResources().getColor(
138                    R.color.song_row_favorite_color);
139            Song song = (Song) item;
140            vh.getMediaItemNumberView().setText("" + song.getNumber());
141
142            String songTitle = song.getTitle() + " / " + song.getDescription();
143            vh.getMediaItemNameView().setText(songTitle);
144
145            vh.getMediaItemDurationView().setText("" + song.getDuration());
146
147            if (song.isFavorite()) {
148                vh.getMediaItemNumberView().setTextColor(favoriteTextColor);
149                vh.getMediaItemNameView().setTextColor(favoriteTextColor);
150                vh.getMediaItemDurationView().setTextColor(favoriteTextColor);
151            } else {
152                vh.getMediaItemNumberView().setTextAppearance(
153                        R.style.TextAppearance_Leanback_PlaybackMediaItemNumber);
154                vh.getMediaItemNameView().setTextAppearance(
155                        R.style.TextAppearance_Leanback_PlaybackMediaItemName);
156                vh.getMediaItemDurationView().setTextAppearance(
157                        R.style.TextAppearance_Leanback_PlaybackMediaItemDuration);
158            }
159        }
160    };
161
162    static class SongPresenterSelector extends PresenterSelector {
163        Presenter mRegularPresenter;
164        Presenter mFavoritePresenter;
165
166        /**
167         * Adds a presenter to be used for the given class.
168         */
169        public SongPresenterSelector setSongPresenterRegular(Presenter presenter) {
170            mRegularPresenter = presenter;
171            return this;
172        }
173
174        /**
175         * Adds a presenter to be used for the given class.
176         */
177        public SongPresenterSelector setSongPresenterFavorite(Presenter presenter) {
178            mFavoritePresenter = presenter;
179            return this;
180        }
181
182        @Override
183        public Presenter[] getPresenters() {
184            return new Presenter[]{mRegularPresenter, mFavoritePresenter};
185        }
186
187        @Override
188        public Presenter getPresenter(Object item) {
189            return ( (Song) item).isFavorite() ? mFavoritePresenter : mRegularPresenter;
190        }
191
192    }
193
194    static class TrackListHeaderPresenter extends AbstractMediaListHeaderPresenter {
195
196        TrackListHeaderPresenter() {
197            super();
198        }
199
200        @Override
201        protected void onBindMediaListHeaderViewHolder(ViewHolder vh, Object item) {
202            vh.getHeaderView().setText("Tracklist");
203        }
204    };
205
206    private void addPlaybackControlsRow() {
207        mRowsAdapter = new ArrayObjectAdapter(new ClassPresenterSelector()
208                .addClassPresenterSelector(Song.class, new SongPresenterSelector()
209                        .setSongPresenterRegular(new SongPresenter(getActivity(),
210                                R.style.Theme_Example_LeanbackMusic_RegularSongNumbers))
211                        .setSongPresenterFavorite(new SongPresenter(getActivity(),
212                                R.style.Theme_Example_LeanbackMusic_FavoriteSongNumbers)))
213                .addClassPresenter(TrackListHeader.class, new TrackListHeaderPresenter())
214                .addClassPresenter(PlaybackControlsRow.class,
215                        mGlue.createControlsRowAndPresenter()));
216        mRowsAdapter.add(mGlue.getControlsRow());
217        mRowsAdapter.add(new TrackListHeader());
218        mRowsAdapter.addAll(2, mSongList);
219        setAdapter(mRowsAdapter);
220        setOnItemViewClickedListener(this);
221        setOnItemViewSelectedListener(this);
222    }
223
224    public MusicConsumptionExampleFragment() {
225        super();
226    }
227
228
229
230    @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
231                                        RowPresenter.ViewHolder rowViewHolder, Object row) {
232
233        if (item instanceof  Action) {
234            // if the clicked item is a primary or secondary action in the playback controller
235            mGlue.onActionClicked((Action) item);
236        } else if (row instanceof  Song) {
237            // if a media item row is clicked
238            Song clickedSong = (Song) row;
239            AbstractMediaItemPresenter.ViewHolder songRowVh =
240                    (AbstractMediaItemPresenter.ViewHolder) rowViewHolder;
241
242            // if an action within a media item row is clicked
243            if (item instanceof MultiActionsProvider.MultiAction) {
244                if ( ((MultiActionsProvider.MultiAction) item).getId() == FAVORITE_ACTION_ID) {
245                    MultiActionsProvider.MultiAction favoriteAction =
246                            (MultiActionsProvider.MultiAction) item;
247                    MultiActionsProvider.MultiAction playlistAction =
248                            songRowVh.getMediaItemRowActions()[0];
249                    favoriteAction.incrementIndex();
250                    playlistAction.incrementIndex();;
251
252                    clickedSong.setFavorite(!clickedSong.isFavorite());
253                    songRowVh.notifyDetailsChanged();
254                    songRowVh.notifyActionChanged(playlistAction);
255                    songRowVh.notifyActionChanged(favoriteAction);
256                }
257            } else if (item == null){
258                // if a media item details is clicked, start playing that media item
259                onSongDetailsClicked(clickedSong);
260            }
261
262        }
263
264
265    }
266
267    @Override
268    public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
269                               RowPresenter.ViewHolder rowViewHolder, Object row) {
270    }
271
272
273    public void onSongDetailsClicked(Song song) {
274        int nextSongIndex = mSongList.indexOf(song);
275        mCurrentSongIndex = nextSongIndex;
276        startPlayback();
277    }
278
279
280    @Override public void onMediaFileFinishedPlaying(MediaPlayerGlue.MetaData song) {
281        if (mGlue.repeatOne()) {
282        } else if (mGlue.useShuffle()) {
283            mCurrentSongIndex = (int) (Math.random() * mSongList.size());
284        } else {
285            mCurrentSongIndex++;
286            if (mCurrentSongIndex >= mSongList.size()) {
287                mCurrentSongIndex = 0;
288                if (!mGlue.repeatAll()) {
289                    return;
290                }
291            }
292        }
293        startPlayback();
294    }
295
296    private void startPlayback() {
297        Song song = mSongList.get(mCurrentSongIndex);
298        MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData();
299        metaData.setArtist(song.getDescription());
300        metaData.setTitle(song.getTitle());
301        metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null));
302
303        Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity()));
304        mGlue.setMetaData(metaData);
305        mGlue.setMediaSource(uri);
306        mGlue.startPlayback();
307    }
308}
309