[Android] repeat, muted, volume properties fully working

This commit is contained in:
Baris Sencan 2015-11-05 17:13:35 -08:00
parent 4362e596a8
commit c03c45a362
4 changed files with 116 additions and 105 deletions

View File

@ -4,6 +4,7 @@ const {
StyleSheet, StyleSheet,
requireNativeComponent, requireNativeComponent,
PropTypes, PropTypes,
NativeModules,
} = React; } = React;
const VideoResizeMode = require('./VideoResizeMode'); const VideoResizeMode = require('./VideoResizeMode');
@ -49,13 +50,13 @@ class Video extends Component {
let nativeResizeMode; let nativeResizeMode;
if (resizeMode === VideoResizeMode.stretch) { if (resizeMode === VideoResizeMode.stretch) {
nativeResizeMode = RCTVideo.ScaleToFill; nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleToFill;
} else if (resizeMode === VideoResizeMode.contain) { } else if (resizeMode === VideoResizeMode.contain) {
nativeResizeMode = RCTVideo.ScaleAspectFit; nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleAspectFit;
} else if (resizeMode === VideoResizeMode.cover) { } else if (resizeMode === VideoResizeMode.cover) {
nativeResizeMode = RCTVideo.ScaleAspectFill; nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleAspectFill;
} else { } else {
nativeResizeMode = RCTVideo.ScaleNone; nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleNone;
} }
const nativeProps = Object.assign({}, this.props); const nativeProps = Object.assign({}, this.props);

View File

@ -13,8 +13,11 @@
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" /> <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" /> <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" /> <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" /> <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" /> <afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" /> <option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
@ -24,7 +27,7 @@
</configuration> </configuration>
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager" inherit-compiler-output="false"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" /> <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" /> <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<exclude-output /> <exclude-output />
@ -86,22 +89,23 @@
</content> </content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" /> <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="fbcore-0.6.1" level="project" /> <orderEntry type="library" exported="" name="okhttp-ws-2.4.0" level="project" />
<orderEntry type="library" exported="" name="okio-1.5.0" level="project" /> <orderEntry type="library" exported="" name="library-2.4.0" level="project" />
<orderEntry type="library" exported="" name="drawee-0.6.1" level="project" /> <orderEntry type="library" exported="" name="okhttp-2.4.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" /> <orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" /> <orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" /> <orderEntry type="library" exported="" name="fbcore-0.6.1" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.4.0" level="project" /> <orderEntry type="library" exported="" name="android-scalablevideoview-1.0.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.13.0" level="project" /> <orderEntry type="library" exported="" name="react-native-0.13.0" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-0.6.1" level="project" />
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.6.1" level="project" /> <orderEntry type="library" exported="" name="imagepipeline-okhttp-0.6.1" level="project" />
<orderEntry type="library" exported="" name="okhttp-ws-2.4.0" level="project" /> <orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" /> <orderEntry type="library" exported="" name="imagepipeline-0.6.1" level="project" />
<orderEntry type="library" exported="" name="library-2.4.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
<orderEntry type="library" exported="" name="fresco-0.6.1" level="project" /> <orderEntry type="library" exported="" name="fresco-0.6.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="okio-1.5.0" level="project" />
<orderEntry type="library" exported="" name="drawee-0.6.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
</component> </component>
</module> </module>

View File

@ -17,4 +17,5 @@ android {
dependencies { dependencies {
compile 'com.facebook.react:react-native:0.13.+' compile 'com.facebook.react:react-native:0.13.+'
compile 'com.yqritc:android-scalablevideoview:1.0.1'
} }

View File

@ -1,17 +1,17 @@
package com.brentvatne.react; package com.brentvatne.react;
import android.graphics.Color; import android.content.Context;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.widget.MediaController; import android.view.Gravity;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.VideoView; import android.support.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder; import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ReactProp; import com.facebook.react.uimanager.ReactProp;
import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ThemedReactContext;
import com.yqritc.scalablevideoview.ScalableType;
import com.yqritc.scalablevideoview.ScalableVideoView;
import java.util.Map; import java.util.Map;
@ -24,13 +24,16 @@ public class ReactVideoViewManager extends SimpleViewManager<FrameLayout> {
private static final String PROP_RESIZE_MODE = "resizeMode"; private static final String PROP_RESIZE_MODE = "resizeMode";
private static final String PROP_REPEAT = "repeat"; private static final String PROP_REPEAT = "repeat";
private static final String PROP_PAUSED = "paused"; private static final String PROP_PAUSED = "paused";
private static final String PROP_MUTED = "muted";
private static final String PROP_VOLUME = "volume";
private enum ResizeMode { private boolean mPrepared = false;
SCALE_NONE, SCALE_TO_FILL, SCALE_ASPECT_FIT, SCALE_ASPECT_FILL
}
private ScalableType mResizeMode = ScalableType.LEFT_TOP;
private boolean mRepeat = false; private boolean mRepeat = false;
private boolean mPaused = false; private boolean mPaused = false;
private boolean mMuted = false;
private float mVolume = 1;
@Override @Override
public String getName() { public String getName() {
@ -40,93 +43,74 @@ public class ReactVideoViewManager extends SimpleViewManager<FrameLayout> {
@Override @Override
protected FrameLayout createViewInstance(ThemedReactContext themedReactContext) { protected FrameLayout createViewInstance(ThemedReactContext themedReactContext) {
final FrameLayout container = new FrameLayout(themedReactContext); final FrameLayout container = new FrameLayout(themedReactContext);
final VideoView videoView = new VideoView(themedReactContext); final ScalableVideoView videoView = new ScalableVideoView(themedReactContext);
MediaController mediaController = new MediaController(themedReactContext); final FrameLayout.LayoutParams videoLayout = new FrameLayout.LayoutParams(
mediaController.setAnchorView(videoView); FrameLayout.LayoutParams.WRAP_CONTENT,
mediaController.setVisibility(VideoView.GONE); FrameLayout.LayoutParams.WRAP_CONTENT
videoView.setMediaController(mediaController); );
videoView.setLayoutParams(new FrameLayout.LayoutParams( videoLayout.gravity = Gravity.CENTER;
videoView.setLayoutParams(videoLayout);
container.setLayoutParams(new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT)); FrameLayout.LayoutParams.MATCH_PARENT
));
container.addView(videoView); container.addView(videoView);
return container; return container;
} }
@Override @Override
public
@Nullable @Nullable
Map getExportedViewConstants() { public Map getExportedViewConstants() {
return MapBuilder.of( return MapBuilder.of(
"ScaleNone", ResizeMode.SCALE_NONE.ordinal(), "ScaleNone", ScalableType.LEFT_TOP.ordinal(),
"ScaleToFill", ResizeMode.SCALE_TO_FILL.ordinal(), "ScaleToFill", ScalableType.FIT_XY.ordinal(),
"ScaleAspectFit", ResizeMode.SCALE_ASPECT_FIT.ordinal(), "ScaleAspectFit", ScalableType.FIT_CENTER.ordinal(),
"ScaleAspectFill", ResizeMode.SCALE_ASPECT_FILL.ordinal()); "ScaleAspectFill", ScalableType.CENTER_CROP.ordinal()
);
} }
@ReactProp(name = PROP_SRC) @ReactProp(name = PROP_SRC)
public void setSrc(final FrameLayout container, @Nullable ReadableMap src) { public void setSrc(final FrameLayout container, @Nullable ReadableMap src) {
final VideoView videoView = (VideoView) container.getChildAt(0); final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
try { try {
final String uriString = src.getString("uri"); final String uriString = src.getString("uri");
final boolean isNetwork = src.getBoolean("isNetwork"); final boolean isNetwork = src.getBoolean("isNetwork");
videoView.stopPlayback(); if (mPrepared) {
videoView.stop();
mPrepared = false;
}
if (isNetwork) { if (isNetwork) {
videoView.setVideoPath(uriString); videoView.setDataSource(uriString);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { } else {
Context context = videoView.getContext();
videoView.setRawData(context.getResources().getIdentifier(uriString, "raw", context.getPackageName()));
}
videoView.prepare(new MediaPlayer.OnPreparedListener() {
@Override @Override
public void onPrepared(MediaPlayer mp) { public void onPrepared(MediaPlayer mp) {
mPrepared = true;
applyModifiers(container); applyModifiers(container);
} }
}); });
} else {
videoView.setVideoURI(Uri.parse("android.resource://" + videoView.getContext().getPackageName() +
"/raw/" + uriString));
applyModifiers(container);
}
} catch (Exception e) { } catch (Exception e) {
assertTrue("failed to set video source", false); assertTrue("failed to set video source", false);
} }
} }
@ReactProp(name = PROP_RESIZE_MODE) @ReactProp(name = PROP_RESIZE_MODE)
public void setResizeMode(final FrameLayout container, int resizeModeOrdinal) { public void setResizeMode(final FrameLayout container, final int resizeModeOrdinal) {
final VideoView videoView = (VideoView) container.getChildAt(0); mResizeMode = ScalableType.values()[resizeModeOrdinal];
try { if (mPrepared) {
final ResizeMode resizeMode = ResizeMode.values()[resizeModeOrdinal]; final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
videoView.setScalableType(mResizeMode);
FrameLayout.LayoutParams layoutParams = null; videoView.invalidate();
switch (resizeMode) {
case SCALE_NONE:
layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
break;
case SCALE_TO_FILL:
layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
break;
case SCALE_ASPECT_FIT:
break;
case SCALE_ASPECT_FILL:
break;
}
if (layoutParams != null) {
videoView.setLayoutParams(layoutParams);
container.updateViewLayout(videoView, layoutParams);
}
} catch (Exception e) {
assertTrue("failed to set video resize mode", false);
} }
} }
@ -134,35 +118,56 @@ public class ReactVideoViewManager extends SimpleViewManager<FrameLayout> {
public void setRepeat(final FrameLayout container, final boolean repeat) { public void setRepeat(final FrameLayout container, final boolean repeat) {
mRepeat = repeat; mRepeat = repeat;
if (!mRepeat) { return; } if (mPrepared) {
final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
final VideoView videoView = (VideoView) container.getChildAt(0); videoView.setLooping(mRepeat);
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (mRepeat) {
mp.seekTo(0);
setPaused(container, mPaused);
} }
} }
});
}
@ReactProp(name = PROP_PAUSED) @ReactProp(name = PROP_PAUSED)
public void setPaused(final FrameLayout container, final boolean paused) { public void setPaused(final FrameLayout container, final boolean paused) {
final VideoView videoView = (VideoView) container.getChildAt(0); mPaused = paused;
if (mPrepared) {
final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
videoView.requestFocus(); videoView.requestFocus();
if (!paused) { if (!mPaused) {
videoView.start(); videoView.start();
} else { } else {
videoView.pause(); videoView.pause();
} }
mPaused = paused; }
}
@ReactProp(name = PROP_MUTED)
public void setMuted(final FrameLayout container, final boolean muted) {
mMuted = muted;
if (mPrepared) {
final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
if (mMuted) {
videoView.setVolume(0, 0);
} else {
videoView.setVolume(mVolume, mVolume);
}
}
}
@ReactProp(name = PROP_VOLUME)
public void setVolume(final FrameLayout container, final float volume) {
mVolume = volume;
if (mPrepared) {
final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
videoView.setVolume(mVolume, mVolume);
}
} }
private void applyModifiers(final FrameLayout container) { private void applyModifiers(final FrameLayout container) {
setResizeMode(container, mResizeMode.ordinal());
setRepeat(container, mRepeat); setRepeat(container, mRepeat);
setPaused(container, mPaused); setPaused(container, mPaused);
setMuted(container, mMuted);
} }
} }