Java tutorial
/* * Author: Scott Ware <scoot.software@gmail.com> * Copyright (c) 2015 Scott Ware * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.scooter1556.sms.androidtv.fragment; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.provider.MediaStore; import android.support.v17.leanback.app.BackgroundManager; import android.support.v17.leanback.app.DetailsFragment; import android.support.v17.leanback.widget.Action; import android.support.v17.leanback.widget.ArrayObjectAdapter; import android.support.v17.leanback.widget.ClassPresenterSelector; import android.support.v17.leanback.widget.DetailsOverviewRow; import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter; import android.support.v17.leanback.widget.HeaderItem; import android.support.v17.leanback.widget.ListRow; import android.support.v17.leanback.widget.ListRowPresenter; import android.support.v17.leanback.widget.OnActionClickedListener; import android.support.v17.leanback.widget.OnItemViewClickedListener; import android.support.v17.leanback.widget.Presenter; import android.support.v17.leanback.widget.Row; import android.support.v17.leanback.widget.RowPresenter; import android.support.v17.leanback.widget.SparseArrayObjectAdapter; import android.support.v4.content.ContextCompat; import android.util.DisplayMetrics; import android.view.MenuItem; import android.view.View; import android.widget.PopupMenu; import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.SimpleTarget; import com.google.gson.Gson; import com.loopj.android.http.JsonHttpResponseHandler; import com.scooter1556.sms.androidtv.R; import com.scooter1556.sms.androidtv.activity.AudioPlayerActivity; import com.scooter1556.sms.androidtv.activity.DirectoryDetailsActivity; import com.scooter1556.sms.androidtv.presenter.DetailsDescriptionPresenter; import com.scooter1556.sms.androidtv.presenter.MediaElementPresenter; import com.scooter1556.sms.lib.android.domain.MediaElement; import com.scooter1556.sms.lib.android.service.AudioPlayerService; import com.scooter1556.sms.lib.android.service.RESTService; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; public class AudioDirectoryDetailsFragment extends DetailsFragment implements PopupMenu.OnMenuItemClickListener { private static final String TAG = "AudioDirectoryDetailsFragment"; private static final int ACTION_PLAY = 0; private static final int ACTION_ADD_AND_PLAY = 1; private static final int ACTION_ADD_TO_PLAYLIST = 2; private static final int DETAIL_THUMB_WIDTH = 274; private static final int DETAIL_THUMB_HEIGHT = 274; private MediaElement mediaElement; private MediaElement selectedMediaElement; List<MediaElement> mediaElements; private ArrayObjectAdapter adapter; private ClassPresenterSelector presenterSelector; private BackgroundManager backgroundManager; private Drawable defaultBackground; private DisplayMetrics displayMetrics; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); prepareBackgroundManager(); mediaElement = ((DirectoryDetailsActivity) getActivity()).getMediaElement(); setupAdapter(); setupDetailsOverview(); getContents(); setBackground(); // Set search icon color. setSearchAffordanceColor(ContextCompat.getColor(getActivity(), R.color.search_opaque)); // When a Related Movie item is clicked. setOnItemViewClickedListener(new ItemViewClickedListener()); setOnSearchClickedListener(new View.OnClickListener() { @Override public void onClick(View view) { // ToDo: Implement search feature Toast.makeText(getActivity(), getString(R.string.error_search_not_implemented), Toast.LENGTH_SHORT) .show(); } }); } @Override public void onStop() { backgroundManager.release(); super.onStop(); } private void prepareBackgroundManager() { // Setup background manager backgroundManager = BackgroundManager.getInstance(getActivity()); backgroundManager.attach(getActivity().getWindow()); // Get default background defaultBackground = getResources().getDrawable(R.drawable.default_background, null); backgroundManager.setDrawable(defaultBackground); // Get screen size displayMetrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); } private void setBackground() { Glide.with(getActivity()) .load(RESTService.getInstance().getConnection().getUrl() + "/image/" + mediaElement.getID() + "/fanart/" + displayMetrics.widthPixels) .asBitmap().into(new SimpleTarget<Bitmap>(displayMetrics.widthPixels, displayMetrics.heightPixels) { @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { backgroundManager.setBitmap(resource); } @Override public void onLoadFailed(Exception e, Drawable errorDrawable) { backgroundManager.setDrawable(defaultBackground); } }); } private void setupAdapter() { // Set detail background and style. FullWidthDetailsOverviewRowPresenter detailsPresenter = new FullWidthDetailsOverviewRowPresenter( new DetailsDescriptionPresenter()); detailsPresenter.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.selected_background)); detailsPresenter.setInitialState(FullWidthDetailsOverviewRowPresenter.STATE_FULL); prepareEntranceTransition(); detailsPresenter.setOnActionClickedListener(new OnActionClickedListener() { @Override public void onActionClicked(Action action) { if (action.getId() == ACTION_PLAY) { if (mediaElements == null) { return; } ArrayList<MediaElement> audioElements = new ArrayList<>(); for (MediaElement element : mediaElements) { if (element.getType().equals(MediaElement.MediaElementType.AUDIO)) { audioElements.add(element); } } // Start playing ((DirectoryDetailsActivity) getActivity()).getAudioPlayerService().playAll(audioElements); // Load audio player interface Intent intent = new Intent(getActivity(), AudioPlayerActivity.class); getActivity().startActivity(intent); } else if (action.getId() == ACTION_ADD_AND_PLAY) { if (mediaElements == null) { return; } ArrayList<MediaElement> audioElements = new ArrayList<>(); for (MediaElement element : mediaElements) { if (element.getType().equals(MediaElement.MediaElementType.AUDIO)) { audioElements.add(element); } } ((DirectoryDetailsActivity) getActivity()).getAudioPlayerService() .addAllAndPlayNext(audioElements); Toast.makeText(getActivity(), getString(R.string.details_audio_directory_play_next), Toast.LENGTH_SHORT).show(); } else if (action.getId() == ACTION_ADD_TO_PLAYLIST) { if (mediaElements == null) { return; } ArrayList<MediaElement> audioElements = new ArrayList<>(); for (MediaElement element : mediaElements) { if (element.getType().equals(MediaElement.MediaElementType.AUDIO)) { audioElements.add(element); } } ((DirectoryDetailsActivity) getActivity()).getAudioPlayerService().addAllToQueue(audioElements); Toast.makeText(getActivity(), getString(R.string.details_audio_directory_add_to_queue), Toast.LENGTH_SHORT).show(); } } }); presenterSelector = new ClassPresenterSelector(); presenterSelector.addClassPresenter(DetailsOverviewRow.class, detailsPresenter); presenterSelector.addClassPresenter(ListRow.class, new ListRowPresenter()); adapter = new ArrayObjectAdapter(presenterSelector); setAdapter(adapter); } private void setupDetailsOverview() { final DetailsOverviewRow row = new DetailsOverviewRow(mediaElement); startEntranceTransition(); Glide.with(getActivity()) .load(RESTService.getInstance().getConnection().getUrl() + "/image/" + mediaElement.getID() + "/cover/" + DETAIL_THUMB_HEIGHT) .asBitmap().dontAnimate().error(defaultBackground).into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(final Bitmap resource, GlideAnimation glideAnimation) { row.setImageBitmap(getActivity(), resource); } }); SparseArrayObjectAdapter actionsAdapter = new SparseArrayObjectAdapter(); actionsAdapter.set(ACTION_PLAY, new Action(ACTION_PLAY, getResources().getString(R.string.action_play), null)); actionsAdapter.set(ACTION_ADD_AND_PLAY, new Action(ACTION_ADD_AND_PLAY, getResources().getString(R.string.action_add_and_play_next), null)); actionsAdapter.set(ACTION_ADD_TO_PLAYLIST, new Action(ACTION_ADD_TO_PLAYLIST, getResources().getString(R.string.action_add_to_queue), null)); row.setActionsAdapter(actionsAdapter); adapter.add(row); } private void setupMediaList() { // Generate tracklist ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new MediaElementPresenter()); HeaderItem header = new HeaderItem(0, getString(R.string.details_audio_directory_list)); for (MediaElement element : mediaElements) { listRowAdapter.add(element); } adapter.add(new ListRow(header, listRowAdapter)); } public void showOptionsMenu(View v) { PopupMenu popup = new PopupMenu(getActivity(), v); // This activity implements OnMenuItemClickListener popup.setOnMenuItemClickListener(this); popup.inflate(R.menu.menu_audio_element); popup.show(); } @Override public boolean onMenuItemClick(MenuItem item) { AudioPlayerService audioPlayerService = ((DirectoryDetailsActivity) getActivity()).getAudioPlayerService(); switch (item.getItemId()) { case R.id.play: if (audioPlayerService != null && selectedMediaElement != null) { audioPlayerService.addAndPlay(selectedMediaElement); } return true; case R.id.play_next: if (audioPlayerService != null && selectedMediaElement != null) { audioPlayerService.addAndPlayNext(selectedMediaElement); } return true; case R.id.add_to_queue: if (audioPlayerService != null && selectedMediaElement != null) { audioPlayerService.addToQueue(selectedMediaElement); } return true; default: return false; } } private final class ItemViewClickedListener implements OnItemViewClickedListener { @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) { if (item instanceof MediaElement) { selectedMediaElement = (MediaElement) item; showOptionsMenu(itemViewHolder.view); } } } private void getContents() { // Fetch recently added media RESTService.getInstance().getMediaElementContents(mediaElement.getID(), new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, JSONObject response) { Gson parser = new Gson(); mediaElements = new ArrayList<>(); mediaElements.add(parser.fromJson(response.toString(), MediaElement.class)); setupMediaList(); } @Override public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, JSONArray response) { Gson parser = new Gson(); mediaElements = new ArrayList<>(); for (int i = 0; i < response.length(); i++) { try { mediaElements .add(parser.fromJson(response.getJSONObject(i).toString(), MediaElement.class)); } catch (JSONException e) { Toast.makeText(getActivity(), getString(R.string.error_parsing_media), Toast.LENGTH_SHORT) .show(); } } setupMediaList(); } @Override public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, Throwable throwable, JSONObject response) { Toast.makeText(getActivity(), getString(R.string.error_fetching_recently_added), Toast.LENGTH_SHORT) .show(); } @Override public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, Throwable throwable, JSONArray response) { Toast.makeText(getActivity(), getString(R.string.error_fetching_recently_added), Toast.LENGTH_SHORT) .show(); } }); } }