diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ac5a9f..a0dd5543 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Changelog -### vNEXT +### Next Version +* Basic fullscreen support for Android MediaPlayer [#1138](https://github.com/react-native-community/react-native-video/pull/1138) * Support video cachging for iOS ([#955](https://github.com/react-native-community/react-native-video/pull/955)) ### Version 3.1.0 diff --git a/README.md b/README.md index 0da3a4df..dce6b6ec 100644 --- a/README.md +++ b/README.md @@ -217,21 +217,8 @@ using System.Collections.Generic; onBuffer={this.onBuffer} // Callback when remote video is buffering onEnd={this.onEnd} // Callback when playback finishes onError={this.videoError} // Callback when video cannot be loaded - onFullscreenPlayerWillPresent={this.fullScreenPlayerWillPresent} // Callback before fullscreen starts - onFullscreenPlayerDidPresent={this.fullScreenPlayerDidPresent} // Callback after fullscreen started - onFullscreenPlayerWillDismiss={this.fullScreenPlayerWillDismiss} // Callback before fullscreen stops - onFullscreenPlayerDidDismiss={this.fullScreenPlayerDidDismiss} // Callback after fullscreen stopped style={styles.backgroundVideo} /> -// Later to trigger fullscreen -this.player.presentFullscreenPlayer() - -// Disable fullscreen -this.player.dismissFullscreenPlayer() - -// To set video position in seconds (seek) -this.player.seek(0) - // Later on in your styles.. var styles = StyleSheet.create({ backgroundVideo: { @@ -266,12 +253,18 @@ var styles = StyleSheet.create({ ### Event props * [onAudioBecomingNoisy](#onaudiobecomingnoisy) +* [onFullscreenPlayerWillPresent](#onfullscreenplayerwillpresent) +* [onFullscreenPlayerDidPresent](#onfullscreenplayerdidpresent) +* [onFullscreenPlayerWillDismiss](#onfullscreenplayerwilldismiss) +* [onFullscreenPlayerDidDismiss](#onfullscreenplayerdiddismiss) * [onLoad](#onload) * [onLoadStart](#onloadstart) * [onProgress](#onprogress) * [onTimedMetadata](#ontimedmetadata) ### Methods +* [dismissFullscreenPlayer](#dismissfullscreenplayer) +* [presentFullscreenPlayer](#presentfullscreenplayer) * [seek](#seek) ### Configurable props @@ -486,6 +479,34 @@ Payload: none Platforms: Android ExoPlayer, iOS +#### onFullscreenPlayerWillPresent +Callback function that is called when the player is about to enter fullscreen mode. + +Payload: none + +Platforms: Android ExoPlayer, Android MediaPlayer, iOS + +#### onFullscreenPlayerDidPresent +Callback function that is called when the player has entered fullscreen mode. + +Payload: none + +Platforms: Android ExoPlayer, Android MediaPlayer, iOS + +#### onFullscreenPlayerWillDismiss +Callback function that is called when the player is about to exit fullscreen mode. + +Payload: none + +Platforms: Android ExoPlayer, Android MediaPlayer, iOS + +#### onFullscreenPlayerDidDismiss +Callback function that is called when the player has exited fullscreen mode. + +Payload: none + +Platforms: Android ExoPlayer, Android MediaPlayer, iOS + #### onLoad Callback function that is called when the media is loaded and ready to play. @@ -595,6 +616,34 @@ return ( ); ``` +#### dismissFullscreenPlayer +`dismissFullscreenPlayer()` + +Take the player out of fullscreen mode. + +Example: +``` +this.player.dismissFullscreenPlayer(); +``` + +Platforms: Android ExoPlayer, Android MediaPlayer, iOS + +#### FullscreenPlayer +`presentFullscreenPlayer()` + +Put the player in fullscreen mode. + +On iOS, this displays the video in a fullscreen view controller with controls. + +On Android ExoPlayer & MediaPlayer, this puts the navigation controls in fullscreen mode. It is not a complete fullscreen implementation, so you will still need to apply a style that makes the width and height match your screen dimensions to get a fullscreen video. + +Example: +``` +this.player.presentFullscreenPlayer(); +``` + +Platforms: Android ExoPlayer, Android MediaPlayer, iOS + #### seek() `seek(seconds)` diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoView.java b/android/src/main/java/com/brentvatne/react/ReactVideoView.java index 954130a1..7cc0aca3 100644 --- a/android/src/main/java/com/brentvatne/react/ReactVideoView.java +++ b/android/src/main/java/com/brentvatne/react/ReactVideoView.java @@ -1,6 +1,7 @@ package com.brentvatne.react; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.res.AssetFileDescriptor; import android.graphics.Matrix; import android.media.MediaPlayer; @@ -9,6 +10,8 @@ import android.os.Build; import android.os.Handler; import android.util.Log; import android.view.MotionEvent; +import android.view.View; +import android.view.Window; import android.webkit.CookieManager; import android.widget.MediaController; @@ -46,7 +49,11 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP EVENT_END("onVideoEnd"), EVENT_STALLED("onPlaybackStalled"), EVENT_RESUME("onPlaybackResume"), - EVENT_READY_FOR_DISPLAY("onReadyForDisplay"); + EVENT_READY_FOR_DISPLAY("onReadyForDisplay"), + EVENT_FULLSCREEN_WILL_PRESENT("onVideoFullscreenPlayerWillPresent"), + EVENT_FULLSCREEN_DID_PRESENT("onVideoFullscreenPlayerDidPresent"), + EVENT_FULLSCREEN_WILL_DISMISS("onVideoFullscreenPlayerWillDismiss"), + EVENT_FULLSCREEN_DID_DISMISS("onVideoFullscreenPlayerDidDismiss"); private final String mName; @@ -106,6 +113,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP private float mActiveRate = 1.0f; private boolean mPlayInBackground = false; private boolean mBackgroundPaused = false; + private boolean mIsFullscreen = false; private int mMainVer = 0; private int mPatchVer = 0; @@ -208,6 +216,9 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP mMediaPlayerValid = false; release(); } + if (mIsFullscreen) { + setFullscreen(false); + } } public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders) { @@ -439,6 +450,39 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP } } + public void setFullscreen(boolean isFullscreen) { + if (isFullscreen == mIsFullscreen) { + return; // Avoid generating events when nothing is changing + } + mIsFullscreen = isFullscreen; + + Activity activity = mThemedReactContext.getCurrentActivity(); + if (activity == null) { + return; + } + Window window = activity.getWindow(); + View decorView = window.getDecorView(); + int uiOptions; + if (mIsFullscreen) { + if (Build.VERSION.SDK_INT >= 19) { // 4.4+ + uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION + | SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | SYSTEM_UI_FLAG_FULLSCREEN; + } else { + uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION + | SYSTEM_UI_FLAG_FULLSCREEN; + } + mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_WILL_PRESENT.toString(), null); + decorView.setSystemUiVisibility(uiOptions); + mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_DID_PRESENT.toString(), null); + } else { + uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; + mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_WILL_DISMISS.toString(), null); + decorView.setSystemUiVisibility(uiOptions); + mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_DID_DISMISS.toString(), null); + } + } + public void applyModifiers() { setResizeModeModifier(mResizeMode); setRepeatModifier(mRepeat); diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java b/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java index 7973121a..dbf152a8 100644 --- a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java +++ b/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java @@ -35,6 +35,7 @@ public class ReactVideoViewManager extends SimpleViewManager { public static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval"; public static final String PROP_SEEK = "seek"; public static final String PROP_RATE = "rate"; + public static final String PROP_FULLSCREEN = "fullscreen"; public static final String PROP_PLAY_IN_BACKGROUND = "playInBackground"; public static final String PROP_CONTROLS = "controls"; @@ -148,6 +149,11 @@ public class ReactVideoViewManager extends SimpleViewManager { videoView.setRateModifier(rate); } + @ReactProp(name = PROP_FULLSCREEN, defaultBoolean = false) + public void setFullscreen(final ReactVideoView videoView, final boolean fullscreen) { + videoView.setFullscreen(fullscreen); + } + @ReactProp(name = PROP_PLAY_IN_BACKGROUND, defaultBoolean = false) public void setPlayInBackground(final ReactVideoView videoView, final boolean playInBackground) { videoView.setPlayInBackground(playInBackground);