/* * Copyright (C) 2015 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 android.support.v17.leanback.supportleanbackshowcase.app.media; import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.support.v17.leanback.app.PlaybackOverlayFragment; import android.support.v17.leanback.supportleanbackshowcase.utils.Constants; import android.support.v17.leanback.supportleanbackshowcase.R; import android.support.v17.leanback.supportleanbackshowcase.utils.Utils; import android.support.v17.leanback.supportleanbackshowcase.models.Song; import android.support.v17.leanback.supportleanbackshowcase.models.SongList; import android.support.v17.leanback.widget.*; import android.support.v17.leanback.widget.AbstractMediaItemPresenter; import android.util.Log; import com.google.gson.Gson; import java.util.List; /** * This example shows how to play music files and build a simple track list. */ public class MusicConsumptionExampleFragment extends PlaybackOverlayFragment implements BaseOnItemViewClickedListener, BaseOnItemViewSelectedListener, MediaPlayerGlue.OnMediaFileFinishedPlayingListener { private static final String TAG = "MusicConsumptionExampleFragment"; private static final int PLAYLIST_ACTION_ID = 0; private static final int FAVORITE_ACTION_ID = 1; private ArrayObjectAdapter mRowsAdapter; private MediaPlayerGlue mGlue; private int mCurrentSongIndex = 0; private List<Song> mSongList; private boolean mAdapterNotified = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Constants.LOCAL_LOGD) Log.d(TAG, "onCreate"); mGlue = new MediaPlayerGlue(getActivity(), this) { @Override protected void onRowChanged(PlaybackControlsRow row) { if (mRowsAdapter == null || mAdapterNotified) return; //mAdapterNotified = true; mRowsAdapter.notifyArrayItemRangeChanged(0, 1); } }; mGlue.setOnMediaFileFinishedPlayingListener(this); String json = Utils.inputStreamToString( getResources().openRawResource(R.raw.music_consumption_example)); mSongList = new Gson().fromJson(json, SongList.class).getSongs(); Resources res = getActivity().getResources(); // For each song add a playlist and favorite actions. for(Song song : mSongList) { MultiActionsProvider.MultiAction[] mediaRowActions = new MultiActionsProvider.MultiAction[2]; MultiActionsProvider.MultiAction playlistAction = new MultiActionsProvider.MultiAction(PLAYLIST_ACTION_ID); Drawable[] playlistActionDrawables = new Drawable[] { res.getDrawable(R.drawable.ic_playlist_add_white_24dp, getActivity().getTheme()), res.getDrawable(R.drawable.ic_playlist_add_filled_24dp, getActivity().getTheme())}; playlistAction.setDrawables(playlistActionDrawables); mediaRowActions[0] = playlistAction; MultiActionsProvider.MultiAction favoriteAction = new MultiActionsProvider.MultiAction(FAVORITE_ACTION_ID); Drawable[] favoriteActionDrawables = new Drawable[] { res.getDrawable(R.drawable.ic_favorite_border_white_24dp, getActivity().getTheme()), res.getDrawable(R.drawable.ic_favorite_filled_24dp, getActivity().getTheme())}; favoriteAction.setDrawables(favoriteActionDrawables); mediaRowActions[1] = favoriteAction; song.setMediaRowActions(mediaRowActions); } Song song = mSongList.get(mCurrentSongIndex); MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData(); metaData.setArtist(song.getDescription()); metaData.setTitle(song.getTitle()); metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null)); Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity())); mGlue.setMetaData(metaData); mGlue.setMediaSource(uri); mGlue.prepareMediaForPlaying(); addPlaybackControlsRow(); } @Override public void onStart() { super.onStart(); mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying()); } @Override public void onStop() { super.onStop(); mGlue.enableProgressUpdating(false); mGlue.reset(); } static class SongPresenter extends AbstractMediaItemPresenter { SongPresenter() { super(); } SongPresenter(Context context, int themeResId) { super(themeResId); setHasMediaRowSeparator(true); } @Override protected void onBindMediaDetails(ViewHolder vh, Object item) { int favoriteTextColor = vh.view.getContext().getResources().getColor( R.color.song_row_favorite_color); Song song = (Song) item; vh.getMediaItemNumberView().setText("" + song.getNumber()); String songTitle = song.getTitle() + " / " + song.getDescription(); vh.getMediaItemNameView().setText(songTitle); vh.getMediaItemDurationView().setText("" + song.getDuration()); if (song.isFavorite()) { vh.getMediaItemNumberView().setTextColor(favoriteTextColor); vh.getMediaItemNameView().setTextColor(favoriteTextColor); vh.getMediaItemDurationView().setTextColor(favoriteTextColor); } else { Context context = vh.getMediaItemNumberView().getContext(); vh.getMediaItemNumberView().setTextAppearance(context, R.style.TextAppearance_Leanback_PlaybackMediaItemNumber); vh.getMediaItemNameView().setTextAppearance(context, R.style.TextAppearance_Leanback_PlaybackMediaItemName); vh.getMediaItemDurationView().setTextAppearance(context, R.style.TextAppearance_Leanback_PlaybackMediaItemDuration); } } }; static class SongPresenterSelector extends PresenterSelector { Presenter mRegularPresenter; Presenter mFavoritePresenter; /** * Adds a presenter to be used for the given class. */ public SongPresenterSelector setSongPresenterRegular(Presenter presenter) { mRegularPresenter = presenter; return this; } /** * Adds a presenter to be used for the given class. */ public SongPresenterSelector setSongPresenterFavorite(Presenter presenter) { mFavoritePresenter = presenter; return this; } @Override public Presenter[] getPresenters() { return new Presenter[]{mRegularPresenter, mFavoritePresenter}; } @Override public Presenter getPresenter(Object item) { return ( (Song) item).isFavorite() ? mFavoritePresenter : mRegularPresenter; } } static class TrackListHeaderPresenter extends AbstractMediaListHeaderPresenter { TrackListHeaderPresenter() { super(); } @Override protected void onBindMediaListHeaderViewHolder(ViewHolder vh, Object item) { vh.getHeaderView().setText("Tracklist"); } }; private void addPlaybackControlsRow() { mRowsAdapter = new ArrayObjectAdapter(new ClassPresenterSelector() .addClassPresenterSelector(Song.class, new SongPresenterSelector() .setSongPresenterRegular(new SongPresenter(getActivity(), R.style.Theme_Example_LeanbackMusic_RegularSongNumbers)) .setSongPresenterFavorite(new SongPresenter(getActivity(), R.style.Theme_Example_LeanbackMusic_FavoriteSongNumbers))) .addClassPresenter(TrackListHeader.class, new TrackListHeaderPresenter()) .addClassPresenter(PlaybackControlsRow.class, mGlue.createControlsRowAndPresenter())); mRowsAdapter.add(mGlue.getControlsRow()); mRowsAdapter.add(new TrackListHeader()); mRowsAdapter.addAll(2, mSongList); setAdapter(mRowsAdapter); setOnItemViewClickedListener(this); setOnItemViewSelectedListener(this); } public MusicConsumptionExampleFragment() { super(); } @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Object row) { if (item instanceof Action) { // if the clicked item is a primary or secondary action in the playback controller mGlue.onActionClicked((Action) item); } else if (row instanceof Song) { // if a media item row is clicked Song clickedSong = (Song) row; AbstractMediaItemPresenter.ViewHolder songRowVh = (AbstractMediaItemPresenter.ViewHolder) rowViewHolder; // if an action within a media item row is clicked if (item instanceof MultiActionsProvider.MultiAction) { if ( ((MultiActionsProvider.MultiAction) item).getId() == FAVORITE_ACTION_ID) { MultiActionsProvider.MultiAction favoriteAction = (MultiActionsProvider.MultiAction) item; MultiActionsProvider.MultiAction playlistAction = songRowVh.getMediaItemRowActions()[0]; favoriteAction.incrementIndex(); playlistAction.incrementIndex();; clickedSong.setFavorite(!clickedSong.isFavorite()); songRowVh.notifyDetailsChanged(); songRowVh.notifyActionChanged(playlistAction); songRowVh.notifyActionChanged(favoriteAction); } } else if (item == null){ // if a media item details is clicked, start playing that media item onSongDetailsClicked(clickedSong); } } } @Override public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Object row) { } public void onSongDetailsClicked(Song song) { int nextSongIndex = mSongList.indexOf(song); mCurrentSongIndex = nextSongIndex; startPlayback(); } @Override public void onMediaFileFinishedPlaying(MediaPlayerGlue.MetaData song) { if (mGlue.repeatOne()) { } else if (mGlue.useShuffle()) { mCurrentSongIndex = (int) (Math.random() * mSongList.size()); } else { mCurrentSongIndex++; if (mCurrentSongIndex >= mSongList.size()) { mCurrentSongIndex = 0; if (!mGlue.repeatAll()) { return; } } } startPlayback(); } private void startPlayback() { Song song = mSongList.get(mCurrentSongIndex); MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData(); metaData.setArtist(song.getDescription()); metaData.setTitle(song.getTitle()); metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null)); Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity())); mGlue.setMetaData(metaData); if (mGlue.setMediaSource(uri)) { mGlue.prepareMediaForPlaying(); } mGlue.startPlayback(); } }