Commit c03c45a3 authored by Baris Sencan's avatar Baris Sencan
Browse files

[Android] repeat, muted, volume properties fully working

parent 4362e596
Loading
Loading
Loading
Loading
+5 −4
Changes for Video.js: 5 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ const {
  StyleSheet,
  requireNativeComponent,
  PropTypes,
  NativeModules,
} = React;

const VideoResizeMode = require('./VideoResizeMode');
@@ -49,13 +50,13 @@ class Video extends Component {

    let nativeResizeMode;
    if (resizeMode === VideoResizeMode.stretch) {
      nativeResizeMode = RCTVideo.ScaleToFill;
      nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleToFill;
    } else if (resizeMode === VideoResizeMode.contain) {
      nativeResizeMode = RCTVideo.ScaleAspectFit;
      nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleAspectFit;
    } else if (resizeMode === VideoResizeMode.cover) {
      nativeResizeMode = RCTVideo.ScaleAspectFill;
      nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleAspectFill;
    } else {
      nativeResizeMode = RCTVideo.ScaleNone;
      nativeResizeMode = NativeModules.UIManager.RCTVideo.Constants.ScaleNone;
    }

    const nativeProps = Object.assign({}, this.props);
+18 −14
Changes for android/RCTVideo.iml: 18 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -13,8 +13,11 @@
        <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
        <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
        <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
        <option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
        <option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
        <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
        <afterSyncTasks>
          <task>generateDebugAndroidTestSources</task>
          <task>generateDebugSources</task>
        </afterSyncTasks>
        <option name="ALLOW_USER_CONFIGURATION" value="false" />
        <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
        <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
@@ -24,7 +27,7 @@
      </configuration>
    </facet>
  </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-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
    <exclude-output />
@@ -86,22 +89,23 @@
    </content>
    <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" exported="" name="fbcore-0.6.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="support-v4-23.0.1" level="project" />
    <orderEntry type="library" exported="" name="okhttp-ws-2.4.0" level="project" />
    <orderEntry type="library" exported="" name="library-2.4.0" level="project" />
    <orderEntry type="library" exported="" name="okhttp-2.4.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="appcompat-v7-23.0.1" level="project" />
    <orderEntry type="library" exported="" name="okhttp-2.4.0" level="project" />
    <orderEntry type="library" exported="" name="fbcore-0.6.1" 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="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="okhttp-ws-2.4.0" level="project" />
    <orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
    <orderEntry type="library" exported="" name="imagepipeline-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="library-2.4.0" 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" />
    <orderEntry type="library" exported="" name="fresco-0.6.1" level="project" />
  </component>
</module>
 No newline at end of file
+1 −0
Changes for android/build.gradle: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -17,4 +17,5 @@ android {

dependencies {
    compile 'com.facebook.react:react-native:0.13.+'
    compile 'com.yqritc:android-scalablevideoview:1.0.1'
}
+83 −78
Changes for android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java: 83 added lines, 78 removed lines.
Original line number Diff line number Diff line
package com.brentvatne.react;

import android.graphics.Color;
import android.content.Context;
import android.media.MediaPlayer;
import android.widget.MediaController;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.VideoView;
import android.support.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ReactProp;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.yqritc.scalablevideoview.ScalableType;
import com.yqritc.scalablevideoview.ScalableVideoView;

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_REPEAT = "repeat";
    private static final String PROP_PAUSED = "paused";
    private static final String PROP_MUTED = "muted";
    private static final String PROP_VOLUME = "volume";

    private enum ResizeMode {
        SCALE_NONE, SCALE_TO_FILL, SCALE_ASPECT_FIT, SCALE_ASPECT_FILL
    }
    private boolean mPrepared = false;

    private ScalableType mResizeMode = ScalableType.LEFT_TOP;
    private boolean mRepeat = false;
    private boolean mPaused = false;
    private boolean mMuted = false;
    private float mVolume = 1;

    @Override
    public String getName() {
@@ -40,93 +43,74 @@ public class ReactVideoViewManager extends SimpleViewManager<FrameLayout> {
    @Override
    protected FrameLayout createViewInstance(ThemedReactContext themedReactContext) {
        final FrameLayout container = new FrameLayout(themedReactContext);
        final VideoView videoView = new VideoView(themedReactContext);
        final ScalableVideoView videoView = new ScalableVideoView(themedReactContext);

        MediaController mediaController = new MediaController(themedReactContext);
        mediaController.setAnchorView(videoView);
        mediaController.setVisibility(VideoView.GONE);
        videoView.setMediaController(mediaController);
        videoView.setLayoutParams(new FrameLayout.LayoutParams(
        final FrameLayout.LayoutParams videoLayout = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
                FrameLayout.LayoutParams.WRAP_CONTENT
        );
        videoLayout.gravity = Gravity.CENTER;
        videoView.setLayoutParams(videoLayout);

        container.setLayoutParams(new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT));
                FrameLayout.LayoutParams.MATCH_PARENT
        ));
        container.addView(videoView);

        return container;
    }

    @Override
    public
    @Nullable
    Map getExportedViewConstants() {
    public Map getExportedViewConstants() {
        return MapBuilder.of(
                "ScaleNone", ResizeMode.SCALE_NONE.ordinal(),
                "ScaleToFill", ResizeMode.SCALE_TO_FILL.ordinal(),
                "ScaleAspectFit", ResizeMode.SCALE_ASPECT_FIT.ordinal(),
                "ScaleAspectFill", ResizeMode.SCALE_ASPECT_FILL.ordinal());
                "ScaleNone", ScalableType.LEFT_TOP.ordinal(),
                "ScaleToFill", ScalableType.FIT_XY.ordinal(),
                "ScaleAspectFit", ScalableType.FIT_CENTER.ordinal(),
                "ScaleAspectFill", ScalableType.CENTER_CROP.ordinal()
        );
    }

    @ReactProp(name = PROP_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 {
            final String uriString = src.getString("uri");
            final boolean isNetwork = src.getBoolean("isNetwork");

            videoView.stopPlayback();
            if (mPrepared) {
                videoView.stop();
                mPrepared = false;
            }

            if (isNetwork) {
                videoView.setVideoPath(uriString);
                videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                videoView.setDataSource(uriString);
            } else {
                Context context = videoView.getContext();
                videoView.setRawData(context.getResources().getIdentifier(uriString, "raw", context.getPackageName()));
            }

            videoView.prepare(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mPrepared = true;
                    applyModifiers(container);
                }
            });
            } else {
                videoView.setVideoURI(Uri.parse("android.resource://" + videoView.getContext().getPackageName() +
                        "/raw/" + uriString));
                applyModifiers(container);
            }
        } catch (Exception e) {
            assertTrue("failed to set video source", false);
        }
    }

    @ReactProp(name = PROP_RESIZE_MODE)
    public void setResizeMode(final FrameLayout container, int resizeModeOrdinal) {
        final VideoView videoView = (VideoView) container.getChildAt(0);

        try {
            final ResizeMode resizeMode = ResizeMode.values()[resizeModeOrdinal];
    public void setResizeMode(final FrameLayout container, final int resizeModeOrdinal) {
        mResizeMode = ScalableType.values()[resizeModeOrdinal];

            FrameLayout.LayoutParams layoutParams = null;
            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);
        if (mPrepared) {
            final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
            videoView.setScalableType(mResizeMode);
            videoView.invalidate();
        }
    }

@@ -134,35 +118,56 @@ public class ReactVideoViewManager extends SimpleViewManager<FrameLayout> {
    public void setRepeat(final FrameLayout container, final boolean repeat) {
        mRepeat = repeat;

        if (!mRepeat) { return; }

        final VideoView videoView = (VideoView) container.getChildAt(0);
        videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {

                if (mRepeat) {
                    mp.seekTo(0);
                    setPaused(container, mPaused);
        if (mPrepared) {
            final ScalableVideoView videoView = (ScalableVideoView) container.getChildAt(0);
            videoView.setLooping(mRepeat);
        }
    }
        });
    }

    @ReactProp(name = PROP_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();
        if (!paused) {
            if (!mPaused) {
                videoView.start();
            } else {
                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) {
        setResizeMode(container, mResizeMode.ordinal());
        setRepeat(container, mRepeat);
        setPaused(container, mPaused);
        setMuted(container, mMuted);
    }
}