Skip to content

Instantly share code, notes, and snippets.

@eneim
Created September 15, 2018 01:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eneim/b36c84fcd108eaf2361bd26cfb2c044e to your computer and use it in GitHub Desktop.
Save eneim/b36c84fcd108eaf2361bd26cfb2c044e to your computer and use it in GitHub Desktop.
Java 7 compatible
/*
* Copyright (c) 2018 Nam Nguyen, nam@ene.im
*
* 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 im.ene.toro.sample.legacy;
import android.annotation.SuppressLint;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import com.google.android.exoplayer2.C;
import im.ene.toro.ToroPlayer;
import im.ene.toro.ToroPlayer.State;
import im.ene.toro.helper.ToroPlayerHelper;
import im.ene.toro.media.PlaybackInfo;
import im.ene.toro.media.VolumeInfo;
import java.util.HashSet;
import java.util.Set;
import static android.media.MediaPlayer.MEDIA_INFO_BUFFERING_END;
import static android.media.MediaPlayer.MEDIA_INFO_BUFFERING_START;
import static android.media.MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START;
import static im.ene.toro.ToroUtil.checkNotNull;
/**
* @author eneim | 6/11/17.
*
* Helper class for {@link ToroVideoView}. This class makes the playback using {@link
* ToroVideoView} easier by wrapping all necessary components and functionality.
*/
@SuppressWarnings({ "WeakerAccess", "ConstantConditions", "unused" }) //
public class Java7LegacyVideoViewHelper extends ToroPlayerHelper {
private static final String TAG = "Toro:Helper:Legacy";
final PlaybackInfo playbackInfo = new PlaybackInfo();
@NonNull final ToroVideoView playerView;
@NonNull final Uri mediaUri;
MediaPlayer mediaPlayer; // obtain from onPrepared, free at release.
MediaPlayer.OnCompletionListener onCompletionListener;
MediaPlayer.OnPreparedListener onPreparedListener;
ToroPlayer.ErrorListeners errorListeners = new ToroPlayer.ErrorListeners();
@State int playerState = State.STATE_IDLE;
boolean playWhenReady = false; // mimic the ExoPlayer
final VolumeInfo volumeInfo = new VolumeInfo(false, 1f);
public Java7LegacyVideoViewHelper(ToroPlayer player, @NonNull Uri mediaUri) {
super(player);
if (!(player.getPlayerView() instanceof ToroVideoView)) {
throw new IllegalArgumentException("Only support ToroVideoView.");
}
if (mediaUri == null) {
throw new IllegalArgumentException("Media Uri must not be null.");
}
this.playerView = (ToroVideoView) player.getPlayerView();
this.mediaUri = mediaUri;
}
public void setOnCompletionListener(MediaPlayer.OnCompletionListener onCompletionListener) {
this.onCompletionListener = onCompletionListener;
}
public void setOnPreparedListener(MediaPlayer.OnPreparedListener onPreparedListener) {
this.onPreparedListener = onPreparedListener;
}
@SuppressLint("ObsoleteSdkInt")
@Override protected void initialize(@NonNull final PlaybackInfo playbackInfo) {
this.playbackInfo.setResumePosition(playbackInfo.getResumePosition());
final Java7LegacyVideoViewHelper helper = Java7LegacyVideoViewHelper.this;
// On Complete event, we reset the player, re-prepare the VideoView so that it can be re-used.
this.playerView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override public void onCompletion(MediaPlayer mp) {
playerState = State.STATE_END;
onPlayerStateUpdated(playWhenReady, playerState);
if (helper.onCompletionListener != null) {
helper.onCompletionListener.onCompletion(mp);
}
// Reset the player so it can be reused.
if (mediaPlayer != null) {
mediaPlayer.reset();
}
playWhenReady = false; // !!Keeping playWhenReady as true will make a loop playback.
playerView.setVideoURI(mediaUri);
}
});
this.playerView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override public void onPrepared(MediaPlayer mp) {
playerState = State.STATE_READY;
onPlayerStateUpdated(playWhenReady, playerState);
mediaPlayer = mp;
if (helper.onPreparedListener != null) {
helper.onPreparedListener.onPrepared(mp);
}
if (playWhenReady) play();
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
this.playerView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override public boolean onInfo(MediaPlayer mp, int what, int extra) {
boolean handled;
switch (what) {
case MEDIA_INFO_BUFFERING_START:
playerState = State.STATE_BUFFERING;
onPlayerStateUpdated(playWhenReady, playerState);
handled = true;
break;
case MEDIA_INFO_BUFFERING_END:
playerState = State.STATE_READY;
onPlayerStateUpdated(playWhenReady, playerState);
handled = true;
break;
case MEDIA_INFO_VIDEO_RENDERING_START:
handled = true;
break;
default:
handled = false;
break;
}
return handled;
}
});
}
this.playerView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override public boolean onError(MediaPlayer mp, int what, int extra) {
errorListeners.onError(new RuntimeException("Error: " + what + ", " + extra));
return true; // prevent the system error dialog.
}
});
this.playerView.setPlayerEventListener(new ToroVideoView.PlayerEventListener() {
@Override public void onPlay() {
playWhenReady = true;
onPlayerStateUpdated(playWhenReady, playerState);
}
@Override public void onPause() {
playWhenReady = false;
onPlayerStateUpdated(playWhenReady, playerState);
}
});
this.playerView.setVideoURI(mediaUri);
if (this.playbackInfo.getResumePosition() >= 0) {
this.playerView.seekTo((int) this.playbackInfo.getResumePosition());
}
}
@Override public void play() {
this.playerView.start();
}
@Override public void pause() {
updateResumePosition();
this.playerView.pause();
}
@Override public boolean isPlaying() {
return playWhenReady || this.playerView.isPlaying(); // is actually playing or is buffering
}
@NonNull @Override public PlaybackInfo getLatestPlaybackInfo() {
updateResumePosition();
return new PlaybackInfo(C.INDEX_UNSET, playbackInfo.getResumePosition());
}
@Override public void setVolume(float volume) {
this.setVolumeInfo(new VolumeInfo(volume == 0, volume));
}
@Override public float getVolume() {
return volumeInfo.getVolume();
}
@Override public void setVolumeInfo(@NonNull VolumeInfo volumeInfo) {
if (mediaPlayer == null) return;
boolean changed = !this.volumeInfo.equals(checkNotNull(volumeInfo));
if (changed) {
float volume = volumeInfo.isMute() ? 0 : volumeInfo.getVolume();
mediaPlayer.setVolume(volume, volume);
this.volumeInfo.setTo(volumeInfo.isMute(), volumeInfo.getVolume());
if (volumeChangeListeners != null) {
for (ToroPlayer.OnVolumeChangeListener listener : volumeChangeListeners) {
listener.onVolumeChanged(volumeInfo);
}
}
}
}
@NonNull @Override public VolumeInfo getVolumeInfo() {
return this.volumeInfo;
}
// Use a Set to prevent duplicated setup.
protected Set<ToroPlayer.OnVolumeChangeListener> volumeChangeListeners;
@Override
public void addOnVolumeChangeListener(@NonNull ToroPlayer.OnVolumeChangeListener listener) {
if (volumeChangeListeners == null) volumeChangeListeners = new HashSet<>();
volumeChangeListeners.add(checkNotNull(listener));
}
@Override public void removeOnVolumeChangeListener(ToroPlayer.OnVolumeChangeListener listener) {
if (volumeChangeListeners != null) volumeChangeListeners.remove(listener);
}
@Override public void addErrorListener(@NonNull ToroPlayer.OnErrorListener errorListener) {
this.errorListeners.add(checkNotNull(errorListener));
}
@Override public void removeErrorListener(ToroPlayer.OnErrorListener errorListener) {
this.errorListeners.remove(errorListener);
}
void updateResumePosition() {
try {
if (mediaPlayer != null) playbackInfo.setResumePosition(mediaPlayer.getCurrentPosition());
} catch (IllegalStateException er) {
er.printStackTrace();
}
}
@Override public void release() {
this.playerView.setOnCompletionListener(null);
this.playerView.setOnPreparedListener(null);
this.playerView.setPlayerEventListener(null);
this.playerView.setOnErrorListener(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
this.playerView.setOnInfoListener(null);
}
this.mediaPlayer = null;
this.playerState = State.STATE_IDLE;
this.playWhenReady = false;
super.release();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment