Java tutorial
/* * 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 hkapps.playmxtv.Activities; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Movie; import android.media.MediaMetadata; import android.media.MediaPlayer; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.net.Uri; import android.os.Bundle; import android.support.v4.os.BuildCompat; import android.view.KeyEvent; import android.widget.VideoView; import com.bumptech.glide.Glide; import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.SimpleTarget; import hkapps.playmxtv.Fragments.PlaybackOverlayFragment; import hkapps.playmxtv.Model.Ficha; import hkapps.playmxtv.R; /** * PlaybackOverlayActivity for video playback that loads PlaybackOverlayFragment */ public class PlaybackOverlayActivity extends Activity implements PlaybackOverlayFragment.OnPlayPauseClickedListener { private static final String TAG = "PlaybackOverlayActivity"; private VideoView mVideoView; private LeanbackPlaybackState mPlaybackState = LeanbackPlaybackState.IDLE; private MediaSession mSession; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.playback_controls); loadViews(); setupCallbacks(); mSession = new MediaSession(this, "LeanbackSampleApp"); mSession.setCallback(new MediaSessionCallback()); mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); mSession.setActive(true); } @Override public void onDestroy() { super.onDestroy(); mVideoView.suspend(); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { PlaybackOverlayFragment playbackOverlayFragment = (PlaybackOverlayFragment) getFragmentManager() .findFragmentById(R.id.playback_controls_fragment); switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY: playbackOverlayFragment.togglePlayback(false); return true; case KeyEvent.KEYCODE_MEDIA_PAUSE: playbackOverlayFragment.togglePlayback(false); return true; case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: if (mPlaybackState == LeanbackPlaybackState.PLAYING) { playbackOverlayFragment.togglePlayback(false); } else { playbackOverlayFragment.togglePlayback(true); } return true; default: return super.onKeyUp(keyCode, event); } } /** * Implementation of OnPlayPauseClickedListener */ public void onFragmentPlayPause(Ficha.FichaReproducible movie, int position, Boolean playPause) { mVideoView.setVideoPath(movie.getDirectUrl()); if (position == 0 || mPlaybackState == LeanbackPlaybackState.IDLE) { setupCallbacks(); mPlaybackState = LeanbackPlaybackState.IDLE; } if (playPause && mPlaybackState != LeanbackPlaybackState.PLAYING) { mPlaybackState = LeanbackPlaybackState.PLAYING; if (position > 0) { mVideoView.seekTo(position); mVideoView.start(); } } else { mPlaybackState = LeanbackPlaybackState.PAUSED; mVideoView.pause(); } updatePlaybackState(position); updateMetadata(movie); } private void updatePlaybackState(int position) { PlaybackState.Builder stateBuilder = new PlaybackState.Builder() .setActions(PlaybackState.ACTION_PLAY_PAUSE); int state = PlaybackState.STATE_PLAYING; if (mPlaybackState == LeanbackPlaybackState.PAUSED) { state = PlaybackState.STATE_PAUSED; } stateBuilder.setState(state, position, 1.0f); mSession.setPlaybackState(stateBuilder.build()); } private long getAvailableActions() { long actions = PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_PLAY_FROM_SEARCH; return actions; } private void updateMetadata(final Ficha movie) { final MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder(); String title = movie.getTitle().replace("_", " -"); metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, title); metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, movie.getSinopsis()); metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, movie.getPoster()); // And at minimum the title and artist for legacy support metadataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE, title); //metadataBuilder.putString(MediaMetadata.METADATA_KEY_ARTIST, movie.); Glide.with(this).load(Uri.parse(movie.getPoster())).asBitmap().into(new SimpleTarget<Bitmap>(500, 500) { @Override public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { metadataBuilder.putBitmap(MediaMetadata.METADATA_KEY_ART, bitmap); mSession.setMetadata(metadataBuilder.build()); } }); } private void loadViews() { mVideoView = (VideoView) findViewById(R.id.videoView); mVideoView.setFocusable(false); mVideoView.setFocusableInTouchMode(false); } private void setupCallbacks() { mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { String msg = ""; if (extra == MediaPlayer.MEDIA_ERROR_TIMED_OUT) { msg = getString(R.string.video_error_media_load_timeout); } else if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) { msg = getString(R.string.video_error_server_inaccessible); } else { msg = getString(R.string.video_error_unknown_error); } mVideoView.stopPlayback(); mPlaybackState = LeanbackPlaybackState.IDLE; return false; } }); mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { if (mPlaybackState == LeanbackPlaybackState.PLAYING) { mVideoView.start(); } } }); mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mPlaybackState = LeanbackPlaybackState.IDLE; } }); } @Override public void onResume() { super.onResume(); mSession.setActive(true); } @Override public void onPause() { super.onPause(); if (mVideoView.isPlaying()) { if (!requestVisibleBehind(true)) { // Try to play behind launcher, but if it fails, stop playback. stopPlayback(); } } else { requestVisibleBehind(false); } } @Override protected void onStop() { super.onStop(); mSession.release(); } @Override public void onVisibleBehindCanceled() { super.onVisibleBehindCanceled(); } private void stopPlayback() { if (mVideoView != null) { mVideoView.stopPlayback(); } } public static boolean supportsPictureInPicture(Context context) { return BuildCompat.isAtLeastN() && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE); } /* * List of various states that we can be in */ public enum LeanbackPlaybackState { PLAYING, PAUSED, BUFFERING, IDLE } private class MediaSessionCallback extends MediaSession.Callback { } }