diff --git a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java new file mode 100644 index 0000000000..72e09aae4a --- /dev/null +++ b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java @@ -0,0 +1,71 @@ +package com.brentvatne.exoplayer; + +import android.app.Dialog; +import android.content.Context; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageButton; + +import com.google.android.exoplayer2.ui.PlayerControlView; + +public class FullScreenPlayerView extends Dialog { + private final PlayerControlView playerControlView; + private final ExoPlayerView exoPlayerView; + private ViewGroup parent; + private final FrameLayout containerView; + + public FullScreenPlayerView(Context context, ExoPlayerView exoPlayerView, PlayerControlView playerControlView) { + super(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen); + this.playerControlView = playerControlView; + this.exoPlayerView = exoPlayerView; + containerView = new FrameLayout(context); + setContentView(containerView, generateDefaultLayoutParams()); + } + + @Override + protected void onStart() { + parent = (FrameLayout)(exoPlayerView.getParent()); + + parent.removeView(exoPlayerView); + containerView.addView(exoPlayerView, generateDefaultLayoutParams()); + + if (playerControlView != null) { + ImageButton imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen); + imageButton.setBackgroundResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_exit); + imageButton.setContentDescription(getContext().getString(com.google.android.exoplayer2.ui.R.string.exo_controls_fullscreen_exit_description)); + parent.removeView(playerControlView); + containerView.addView(playerControlView, generateDefaultLayoutParams()); + + } + + super.onStart(); + } + + @Override + protected void onStop() { + containerView.removeView(exoPlayerView); + parent.addView(exoPlayerView, generateDefaultLayoutParams()); + + if (playerControlView != null) { + ImageButton imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen); + imageButton.setBackgroundResource(com.google.android.exoplayer2.ui.R.drawable.exo_icon_fullscreen_enter); + imageButton.setContentDescription(getContext().getString(com.google.android.exoplayer2.ui.R.string.exo_controls_fullscreen_enter_description)); + containerView.removeView(playerControlView); + parent.addView(playerControlView, generateDefaultLayoutParams()); + } + + parent.requestLayout(); + parent = null; + + super.onStop(); + } + + private FrameLayout.LayoutParams generateDefaultLayoutParams() { + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT + ); + layoutParams.setMargins(0, 0, 0, 0); + return layoutParams; + } +} diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 3dccad9398..d846202d7c 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -140,6 +140,7 @@ class ReactExoplayerView extends FrameLayout implements private Player.Listener eventListener; private ExoPlayerView exoPlayerView; + private FullScreenPlayerView fullScreenPlayerView; private DataSource.Factory mediaDataSourceFactory; private ExoPlayer player; @@ -378,7 +379,7 @@ public void onClick(View v) { } }); - //Handling the playButton click event + //Handling the playButton click event ImageButton playButton = playerControlView.findViewById(R.id.exo_play); playButton.setOnClickListener(new View.OnClickListener() { @Override @@ -399,6 +400,10 @@ public void onClick(View v) { } }); + //Handling the fullScreenButton click event + ImageButton fullScreenButton = playerControlView.findViewById(R.id.exo_fullscreen); + fullScreenButton.setOnClickListener(v -> setFullscreen(!isFullscreen)); + // Invoking onPlaybackStateChanged and onPlayWhenReadyChanged events for Player eventListener = new Player.Listener() { @Override @@ -655,6 +660,7 @@ private void finishPlayerInitialization() { setControls(controls); applyModifiers(); startBufferCheckTimer(); + fullScreenPlayerView = new FullScreenPlayerView(getContext(), exoPlayerView, playerControlView); } private DrmSessionManager buildDrmSessionManager(UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray) throws UnsupportedDrmException { @@ -861,6 +867,11 @@ private void onStopPlayback() { if (isFullscreen) { setFullscreen(false); } + + if (player != null) { + player.seekTo(0); + setPausedModifier(true); + } audioManager.abandonAudioFocus(this); } @@ -1741,23 +1752,36 @@ public void setFullscreen(boolean fullscreen) { } Window window = activity.getWindow(); View decorView = window.getDecorView(); - int uiOptions; if (isFullscreen) { - if (Util.SDK_INT >= 19) { // 4.4+ - uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION + eventEmitter.fullscreenWillPresent(); + fullScreenPlayerView.show(); + post(() -> { + // for symmetric reason + int uiOptions; + if (Util.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 + } else { + uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_FULLSCREEN; - } - eventEmitter.fullscreenWillPresent(); - decorView.setSystemUiVisibility(uiOptions); + } + decorView.setSystemUiVisibility(uiOptions); + }); eventEmitter.fullscreenDidPresent(); } else { - uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; eventEmitter.fullscreenWillDismiss(); - decorView.setSystemUiVisibility(uiOptions); + fullScreenPlayerView.dismiss(); + reLayout(exoPlayerView); + if (playerControlView != null) { + reLayout(playerControlView); + } + post(() -> { + // it is a must to do it in the post + // otherwise the status bar wont show the text + int uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; + decorView.setSystemUiVisibility(uiOptions); + }); eventEmitter.fullscreenDidDismiss(); } } diff --git a/android/src/main/res/layout/exo_player_control_view.xml b/android/src/main/res/layout/exo_player_control_view.xml index becee6a901..19440912d3 100644 --- a/android/src/main/res/layout/exo_player_control_view.xml +++ b/android/src/main/res/layout/exo_player_control_view.xml @@ -71,6 +71,14 @@ android:paddingRight="4dp" android:includeFontPadding="false" android:textColor="#FFBEBEBE"/> + + diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml new file mode 100644 index 0000000000..3459d9d6e2 --- /dev/null +++ b/android/src/main/res/values/styles.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/examples/basic/package.json b/examples/basic/package.json index 530e822d3b..22658f1a82 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -15,7 +15,7 @@ "babel-plugin-module-resolver": "^4.1.0", "react": "16.13.1", "react-native": "0.63.4", - "react-native-video": "../..", + "react-native-video": "file:../..", "react-native-windows": "0.63.41" }, "devDependencies": { diff --git a/examples/basic/yarn.lock b/examples/basic/yarn.lock index 4eddaeb5cf..c1d4a0c112 100644 --- a/examples/basic/yarn.lock +++ b/examples/basic/yarn.lock @@ -2573,11 +2573,6 @@ electron-to-chromium@^1.4.17: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz#657f2588c048fb95975779f8fea101fad854de89" integrity sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg== -eme-encryption-scheme-polyfill@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/eme-encryption-scheme-polyfill/-/eme-encryption-scheme-polyfill-2.0.4.tgz#7d818302af3f3b19d5974255dcc92dc087413845" - integrity sha512-MHYJX1v145Pjj2YJTrVVuJOYyXrxGVy8LWf6kV5M4jrV/GyoeuJKyTuD+GaD+VAiE8Ip+MptiH4dXk6ZVmMNow== - emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.1.2.tgz#56b140e8f6992375b3d7cb2cab1cc7432d9632e8" @@ -5774,13 +5769,12 @@ react-is@^16.12.0, react-is@^16.13.1, react-is@^16.8.4, react-is@^16.8.6: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-native-video@../..: - version "6.0.0-alpha1" +"react-native-video@file:../..": + version "6.0.0-alpha.1" dependencies: deprecated-react-native-prop-types "^2.2.0" keymirror "^0.1.1" prop-types "^15.7.2" - shaka-player "^3.3.2" react-native-windows@0.63.41: version "0.63.41" @@ -6309,13 +6303,6 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -shaka-player@^3.3.2: - version "3.3.4" - resolved "https://registry.yarnpkg.com/shaka-player/-/shaka-player-3.3.4.tgz#7d137a18fc0f55c50852a4348c8319495b5fa546" - integrity sha512-8PrUBA8aOABGvhQVa59XMoPo5myAoQF4ptx6gvZWPOBtdsyVaamqQKELY77ikZJ1ejup7BmHf42MXGFmxQfcaA== - dependencies: - eme-encryption-scheme-polyfill "^2.0.3" - shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"