From 5c422db78dc2d1afc3ec1682c126939c7cbc76e5 Mon Sep 17 00:00:00 2001 From: Marcin Adamczyk Date: Wed, 29 Jun 2016 14:31:00 +0200 Subject: [PATCH 1/2] add android Stalled and Resume events --- .../com/brentvatne/react/ReactVideoView.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoView.java b/android/src/main/java/com/brentvatne/react/ReactVideoView.java index 7a01cb2a..c5a637d9 100644 --- a/android/src/main/java/com/brentvatne/react/ReactVideoView.java +++ b/android/src/main/java/com/brentvatne/react/ReactVideoView.java @@ -16,7 +16,7 @@ import com.yqritc.scalablevideoview.ScalableType; import com.yqritc.scalablevideoview.ScalableVideoView; public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnPreparedListener, MediaPlayer - .OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, LifecycleEventListener { + .OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener, LifecycleEventListener { public enum Events { EVENT_LOAD_START("onVideoLoadStart"), @@ -24,7 +24,10 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP EVENT_ERROR("onVideoError"), EVENT_PROGRESS("onVideoProgress"), EVENT_SEEK("onVideoSeek"), - EVENT_END("onVideoEnd"); + EVENT_END("onVideoEnd"), + EVENT_STALLED("onPlaybackStalled"), + EVENT_RESUME("onPlaybackResume"), + EVENT_READY_FOR_DISPLAY("onReadyForDisplay"); private final String mName; @@ -79,6 +82,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP private boolean mMediaPlayerValid = false; // True if mMediaPlayer is in prepared, started, or paused state. private int mVideoDuration = 0; private int mVideoBufferedDuration = 0; + private boolean isStalled = false; public ReactVideoView(ThemedReactContext themedReactContext) { super(themedReactContext); @@ -116,6 +120,8 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.setOnBufferingUpdateListener(this); mMediaPlayer.setOnCompletionListener(this); + mMediaPlayer.setOnInfoListener(this); + } } @@ -296,6 +302,26 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP return true; } + @Override + public boolean onInfo(MediaPlayer mp, int what, int extra) { + switch (what) { + case MediaPlayer.MEDIA_INFO_BUFFERING_START: + mEventEmitter.receiveEvent(getId(), Events.EVENT_STALLED.toString(), Arguments.createMap()); + isStalled = true; + break; + case MediaPlayer.MEDIA_INFO_BUFFERING_END: + mEventEmitter.receiveEvent(getId(), Events.EVENT_RESUME.toString(), Arguments.createMap()); + isStalled = false; + break; + case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: + mEventEmitter.receiveEvent(getId(), Events.EVENT_READY_FOR_DISPLAY.toString(), Arguments.createMap()); + break; + + default: + } + return false; + } + @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { mVideoBufferedDuration = (int) Math.round((double) (mVideoDuration * percent) / 100.0); From f62453f714941e81678246a50fc04cc09776b52e Mon Sep 17 00:00:00 2001 From: Marcin Adamczyk Date: Wed, 29 Jun 2016 15:25:28 +0200 Subject: [PATCH 2/2] keep player valid after reaching video end --- .../com/brentvatne/react/ReactVideoView.java | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoView.java b/android/src/main/java/com/brentvatne/react/ReactVideoView.java index c5a637d9..d25b26aa 100644 --- a/android/src/main/java/com/brentvatne/react/ReactVideoView.java +++ b/android/src/main/java/com/brentvatne/react/ReactVideoView.java @@ -1,22 +1,24 @@ package com.brentvatne.react; import android.media.MediaPlayer; +import android.net.Uri; import android.os.Handler; import android.util.Log; -import android.net.Uri; import android.webkit.CookieManager; -import java.util.Map; -import java.util.HashMap; + import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.events.RCTEventEmitter; import com.yqritc.scalablevideoview.ScalableType; import com.yqritc.scalablevideoview.ScalableVideoView; +import java.util.HashMap; +import java.util.Map; + public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnPreparedListener, MediaPlayer - .OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener, LifecycleEventListener { + .OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener, LifecycleEventListener { public enum Events { EVENT_LOAD_START("onVideoLoadStart"), @@ -79,10 +81,10 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP private float mRate = 1.0f; private boolean mPlayInBackground = false; - private boolean mMediaPlayerValid = false; // True if mMediaPlayer is in prepared, started, or paused state. + private boolean mMediaPlayerValid = false; // True if mMediaPlayer is in prepared, started, paused or completed state. private int mVideoDuration = 0; private int mVideoBufferedDuration = 0; - private boolean isStalled = false; + private boolean isCompleted = false; public ReactVideoView(ThemedReactContext themedReactContext) { super(themedReactContext); @@ -98,7 +100,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP @Override public void run() { - if (mMediaPlayerValid) { + if (mMediaPlayerValid && !isCompleted) { WritableMap event = Arguments.createMap(); event.putDouble(EVENT_PROP_CURRENT_TIME, mMediaPlayer.getCurrentPosition() / 1000.0); event.putDouble(EVENT_PROP_PLAYABLE_DURATION, mVideoBufferedDuration / 1000.0); //TODO:mBufferUpdateRunnable @@ -126,6 +128,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP } public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset) { + mSrcUriString = uriString; mSrcType = type; mSrcIsNetwork = isNetwork; @@ -196,6 +199,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP } public void setRepeatModifier(final boolean repeat) { + mRepeat = repeat; if (mMediaPlayerValid) { @@ -204,6 +208,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP } public void setPausedModifier(final boolean paused) { + mPaused = paused; if (!mMediaPlayerValid) { @@ -258,11 +263,13 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP } public void setPlayInBackground(final boolean playInBackground) { + mPlayInBackground = playInBackground; } @Override public void onPrepared(MediaPlayer mp) { + mMediaPlayerValid = true; mVideoDuration = mp.getDuration(); @@ -293,6 +300,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP @Override public boolean onError(MediaPlayer mp, int what, int extra) { + WritableMap error = Arguments.createMap(); error.putInt(EVENT_PROP_WHAT, what); error.putInt(EVENT_PROP_EXTRA, extra); @@ -307,11 +315,9 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP switch (what) { case MediaPlayer.MEDIA_INFO_BUFFERING_START: mEventEmitter.receiveEvent(getId(), Events.EVENT_STALLED.toString(), Arguments.createMap()); - isStalled = true; break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: mEventEmitter.receiveEvent(getId(), Events.EVENT_RESUME.toString(), Arguments.createMap()); - isStalled = false; break; case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: mEventEmitter.receiveEvent(getId(), Events.EVENT_READY_FOR_DISPLAY.toString(), Arguments.createMap()); @@ -337,35 +343,42 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP mEventEmitter.receiveEvent(getId(), Events.EVENT_SEEK.toString(), event); super.seekTo(msec); + if (isCompleted && mVideoDuration != 0 && msec < mVideoDuration) { + isCompleted = false; + } } } @Override public void onCompletion(MediaPlayer mp) { - mMediaPlayerValid = false; + + isCompleted = true; mEventEmitter.receiveEvent(getId(), Events.EVENT_END.toString(), null); } @Override protected void onDetachedFromWindow() { + mMediaPlayerValid = false; super.onDetachedFromWindow(); } @Override protected void onAttachedToWindow() { + super.onAttachedToWindow(); setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset); } @Override public void onHostPause() { + if (mMediaPlayer != null && !mPlayInBackground) { mMediaPlayer.pause(); } } - @Override + @Override public void onHostResume() { }