From d174b1a465b069e0910ab8fc4ac3856207fa4481 Mon Sep 17 00:00:00 2001 From: Baris Sencan Date: Mon, 9 Nov 2015 17:54:15 -0800 Subject: [PATCH] [Android] Better code structure --- .../com/brentvatne/react/ReactVideoView.java | 107 ++++++++++++++ .../react/ReactVideoViewManager.java | 138 +++++++----------- 2 files changed, 156 insertions(+), 89 deletions(-) create mode 100644 android/src/main/java/com/brentvatne/react/ReactVideoView.java diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoView.java b/android/src/main/java/com/brentvatne/react/ReactVideoView.java new file mode 100644 index 00000000..479cc601 --- /dev/null +++ b/android/src/main/java/com/brentvatne/react/ReactVideoView.java @@ -0,0 +1,107 @@ +package com.brentvatne.react; + +import android.content.Context; +import android.media.MediaPlayer; +import android.os.Handler; +import com.facebook.react.bridge.Arguments; +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; + +public class ReactVideoView extends ScalableVideoView { + + private ThemedReactContext mThemedReactContext; + + private Handler mProgressUpdateHandler = new Handler(); + private Runnable mProgressUpdateRunnable = null; + + private ScalableType mResizeMode = ScalableType.LEFT_TOP; + private boolean mRepeat = false; + private boolean mPaused = false; + private boolean mMuted = false; + private float mVolume = 1; + + public ReactVideoView(ThemedReactContext themedReactContext) { + super(themedReactContext); + + mThemedReactContext = themedReactContext; + + mMediaPlayer = new MediaPlayer(); + mMediaPlayer.setOnVideoSizeChangedListener(this); + setSurfaceTextureListener(this); + + mProgressUpdateRunnable = new Runnable() { + @Override + public void run() { + final RCTEventEmitter eventEmitter = getEventEmitter(); + + if (mMediaPlayer.isPlaying()) { + WritableMap event = Arguments.createMap(); + // TODO: Other event properties. + event.putDouble("currentTime", (double) mMediaPlayer.getCurrentPosition() / (double) 1000); + event.putDouble("duration", (double) mMediaPlayer.getDuration() / (double) 1000); + eventEmitter.receiveEvent(getId(), ReactVideoViewManager.EVENT_PROGRESS, event); + } + mProgressUpdateHandler.postDelayed(mProgressUpdateRunnable, 250); + } + }; + mProgressUpdateHandler.post(mProgressUpdateRunnable); + } + + private RCTEventEmitter getEventEmitter() { + return mThemedReactContext.getJSModule(RCTEventEmitter.class); + } + + public void reset() { + mMediaPlayer.reset(); + } + + public void setResizeModeModifier(final ScalableType resizeMode) { + mResizeMode = resizeMode; + setScalableType(resizeMode); + invalidate(); + } + + public void setRepeatModifier(final boolean repeat) { + mRepeat = repeat; + setLooping(repeat); + } + + public void setPausedModifier(final boolean paused) { + mPaused = paused; + + try { + if (!mPaused) { + start(); + } else { + pause(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void setMutedModifier(final boolean muted) { + mMuted = muted; + + if (mMuted) { + setVolume(0, 0); + } else { + setVolume(mVolume, mVolume); + } + } + + public void setVolumeModifier(final float volume) { + mVolume = volume; + setMutedModifier(mMuted); + } + + public void applyModifiers() { + setResizeModeModifier(mResizeMode); + setRepeatModifier(mRepeat); + setPausedModifier(mPaused); + setVolumeModifier(mVolume); + } +} diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java b/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java index c7ff3b5f..b1fb1729 100644 --- a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java +++ b/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java @@ -11,30 +11,28 @@ import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.events.RCTEventEmitter; import com.yqritc.scalablevideoview.ScalableType; -import com.yqritc.scalablevideoview.ScalableVideoView; import javax.annotation.Nullable; import java.util.Map; -import static junit.framework.Assert.assertTrue; - -public class ReactVideoViewManager extends SimpleViewManager { +public class ReactVideoViewManager extends SimpleViewManager { public static final String REACT_CLASS = "RCTVideo"; - private static final String PROP_SRC = "src"; - private static final String PROP_RESIZE_MODE = "resizeMode"; - private static final String PROP_REPEAT = "repeat"; - private static final String PROP_PAUSED = "paused"; - private static final String PROP_MUTED = "muted"; - private static final String PROP_VOLUME = "volume"; - private boolean mPrepared = false; + public static final String PROP_SRC = "src"; + public static final String PROP_SRC_URI = "uri"; + public static final String PROP_SRC_TYPE = "type"; + public static final String PROP_SRC_IS_NETWORK = "isNetwork"; + public static final String PROP_RESIZE_MODE = "resizeMode"; + public static final String PROP_REPEAT = "repeat"; + public static final String PROP_PAUSED = "paused"; + public static final String PROP_MUTED = "muted"; + public static final String PROP_VOLUME = "volume"; - private ScalableType mResizeMode = ScalableType.LEFT_TOP; - private boolean mRepeat = false; - private boolean mPaused = false; - private boolean mMuted = false; - private float mVolume = 1; + public static final String EVENT_LOAD_START = "onVideoLoadStart"; + public static final String EVENT_LOAD = "onVideoLoad"; + public static final String EVENT_PROGRESS = "onVideoProgress"; + public static final String EVENT_END = "onVideoEnd"; @Override public String getName() { @@ -42,17 +40,18 @@ public class ReactVideoViewManager extends SimpleViewManager } @Override - protected ScalableVideoView createViewInstance(ThemedReactContext themedReactContext) { - return new ScalableVideoView(themedReactContext); + protected ReactVideoView createViewInstance(ThemedReactContext themedReactContext) { + return new ReactVideoView(themedReactContext); } @Override @Nullable public Map getExportedCustomDirectEventTypeConstants() { return MapBuilder.builder() - .put("onVideoLoadStart", MapBuilder.of("registrationName", "onVideoLoadStart")) - .put("onVideoLoad", MapBuilder.of("registrationName", "onVideoLoad")) - .put("onVideoEnd", MapBuilder.of("registrationName", "onVideoEnd")) + .put(EVENT_LOAD_START, MapBuilder.of("registrationName", EVENT_LOAD_START)) + .put(EVENT_LOAD, MapBuilder.of("registrationName", EVENT_LOAD)) + .put(EVENT_PROGRESS, MapBuilder.of("registrationName", EVENT_PROGRESS)) + .put(EVENT_END, MapBuilder.of("registrationName", EVENT_END)) .build(); } @@ -60,27 +59,24 @@ public class ReactVideoViewManager extends SimpleViewManager @Nullable public Map getExportedViewConstants() { return MapBuilder.of( - "ScaleNone", ScalableType.LEFT_TOP.ordinal(), - "ScaleToFill", ScalableType.FIT_XY.ordinal(), - "ScaleAspectFit", ScalableType.FIT_CENTER.ordinal(), - "ScaleAspectFill", ScalableType.CENTER_CROP.ordinal() + "ScaleNone", Integer.toString(ScalableType.LEFT_TOP.ordinal()), + "ScaleToFill", Integer.toString(ScalableType.FIT_XY.ordinal()), + "ScaleAspectFit", Integer.toString(ScalableType.FIT_CENTER.ordinal()), + "ScaleAspectFill", Integer.toString(ScalableType.CENTER_CROP.ordinal()) ); } @ReactProp(name = PROP_SRC) - public void setSrc(final ScalableVideoView videoView, @Nullable ReadableMap src) { + public void setSrc(final ReactVideoView videoView, @Nullable ReadableMap src) { final ThemedReactContext themedReactContext = (ThemedReactContext) videoView.getContext(); final RCTEventEmitter eventEmitter = themedReactContext.getJSModule(RCTEventEmitter.class); try { - final String uriString = src.getString("uri"); - final String type = src.getString("type"); - final boolean isNetwork = src.getBoolean("isNetwork"); + final String uriString = src.getString(PROP_SRC_URI); + final String type = src.getString(PROP_SRC_TYPE); + final boolean isNetwork = src.getBoolean(PROP_SRC_IS_NETWORK); - if (mPrepared) { - videoView.stop(); - mPrepared = false; - } + videoView.reset(); if (isNetwork) { videoView.setDataSource(uriString); @@ -90,17 +86,17 @@ public class ReactVideoViewManager extends SimpleViewManager } WritableMap writableSrc = Arguments.createMap(); - writableSrc.putString("uri", uriString); - writableSrc.putString("type", type); - writableSrc.putBoolean("isNetwork", isNetwork); + writableSrc.putString(PROP_SRC_URI, uriString); + writableSrc.putString(PROP_SRC_TYPE, type); + writableSrc.putBoolean(PROP_SRC_IS_NETWORK, isNetwork); WritableMap event = Arguments.createMap(); - event.putMap("src", writableSrc); - eventEmitter.receiveEvent(videoView.getId(), "onVideoLoadStart", event); + event.putMap(PROP_SRC, writableSrc); + eventEmitter.receiveEvent(videoView.getId(), EVENT_LOAD_START, event); videoView.prepare(new MediaPlayer.OnPreparedListener() { @Override - public void onPrepared(MediaPlayer mp) { - mPrepared = true; + public void onPrepared(final MediaPlayer mp) { + mp.setScreenOnWhilePlaying(true); mp.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override @@ -113,7 +109,7 @@ public class ReactVideoViewManager extends SimpleViewManager mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { - eventEmitter.receiveEvent(videoView.getId(), "onVideoEnd", null); + eventEmitter.receiveEvent(videoView.getId(), EVENT_END, null); } }); @@ -121,9 +117,9 @@ public class ReactVideoViewManager extends SimpleViewManager event.putDouble("duration", (double) mp.getDuration() / (double) 1000); event.putDouble("currentTime", (double) mp.getCurrentPosition() / (double) 1000); // TODO: Add canX properties. - eventEmitter.receiveEvent(videoView.getId(), "onVideoLoad", event); + eventEmitter.receiveEvent(videoView.getId(), EVENT_LOAD, event); - applyModifiers(videoView); + videoView.applyModifiers(); } }); } catch (Exception e) { @@ -132,63 +128,27 @@ public class ReactVideoViewManager extends SimpleViewManager } @ReactProp(name = PROP_RESIZE_MODE) - public void setResizeMode(final ScalableVideoView videoView, final int resizeModeOrdinal) { - mResizeMode = ScalableType.values()[resizeModeOrdinal]; - - if (mPrepared) { - videoView.setScalableType(mResizeMode); - videoView.invalidate(); - } + public void setResizeMode(final ReactVideoView videoView, final String resizeModeOrdinalString) { + videoView.setResizeModeModifier(ScalableType.values()[Integer.parseInt(resizeModeOrdinalString)]); } @ReactProp(name = PROP_REPEAT) - public void setRepeat(final ScalableVideoView videoView, final boolean repeat) { - mRepeat = repeat; - - if (mPrepared) { - videoView.setLooping(mRepeat); - } + public void setRepeat(final ReactVideoView videoView, final boolean repeat) { + videoView.setRepeatModifier(repeat); } @ReactProp(name = PROP_PAUSED) - public void setPaused(final ScalableVideoView videoView, final boolean paused) { - mPaused = paused; - - if (mPrepared) { - if (!mPaused) { - videoView.start(); - } else { - videoView.pause(); - } - } + public void setPaused(final ReactVideoView videoView, final boolean paused) { + videoView.setPausedModifier(paused); } @ReactProp(name = PROP_MUTED) - public void setMuted(final ScalableVideoView videoView, final boolean muted) { - mMuted = muted; - - if (mPrepared) { - if (mMuted) { - videoView.setVolume(0, 0); - } else { - videoView.setVolume(mVolume, mVolume); - } - } + public void setMuted(final ReactVideoView videoView, final boolean muted) { + videoView.setMutedModifier(muted); } @ReactProp(name = PROP_VOLUME) - public void setVolume(final ScalableVideoView videoView, final float volume) { - mVolume = volume; - - if (mPrepared) { - videoView.setVolume(mVolume, mVolume); - } - } - - private void applyModifiers(final ScalableVideoView videoView) { - setResizeMode(videoView, mResizeMode.ordinal()); - setRepeat(videoView, mRepeat); - setPaused(videoView, mPaused); - setMuted(videoView, mMuted); + public void setVolume(final ReactVideoView videoView, final float volume) { + videoView.setVolumeModifier(volume); } }