diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 3535ad445f..7fbf91596d 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -1,3 +1,9 @@
+
+
+
diff --git a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java
new file mode 100644
index 0000000000..0fdd1e403d
--- /dev/null
+++ b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java
@@ -0,0 +1,155 @@
+package com.brentvatne.exoplayer;
+
+import android.content.pm.ActivityInfo;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.brentvatne.react.R;
+import com.google.android.exoplayer2.Player;
+import com.google.android.exoplayer2.ExoPlayer;
+import com.google.android.exoplayer2.ui.PlayerControlView;
+
+public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implements ReactExoplayerView.FullScreenDelegate {
+ public static final String EXTRA_EXO_PLAYER_VIEW_ID = "extra_id";
+ public static final String EXTRA_ORIENTATION = "extra_orientation";
+
+ private ReactExoplayerView exoplayerView;
+ private PlayerControlView playerControlView;
+ private ExoPlayer player;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ int exoplayerViewId = getIntent().getIntExtra(EXTRA_EXO_PLAYER_VIEW_ID, -1);
+ exoplayerView = ReactExoplayerView.getViewInstance(exoplayerViewId);
+ if (exoplayerView == null) {
+ finish();
+ return;
+ }
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ String orientation = getIntent().getStringExtra(EXTRA_ORIENTATION);
+ if ("landscape".equals(orientation)) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ } else if ("portrait".equals(orientation)) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
+ }
+ setContentView(R.layout.exo_player_fullscreen_video);
+ player = exoplayerView.getPlayer();
+
+ ExoPlayerView playerView = findViewById(R.id.player_view);
+ playerView.setPlayer(player);
+ playerView.setOnClickListener(v -> togglePlayerControlVisibility());
+
+ playerControlView = findViewById(R.id.player_controls);
+ playerControlView.setPlayer(player);
+ // Set the fullscreen button to "close fullscreen" icon
+ ImageView fullscreenIcon = playerControlView.findViewById(R.id.exo_fullscreen_icon);
+ fullscreenIcon.setImageResource(R.drawable.exo_controls_fullscreen_exit);
+ playerControlView.findViewById(R.id.exo_fullscreen_button)
+ .setOnClickListener(v -> {
+ if (exoplayerView != null) {
+ exoplayerView.setFullscreen(false);
+ }
+ });
+ //Handling the playButton click event
+ playerControlView.findViewById(R.id.exo_play).setOnClickListener(v -> {
+ if (player != null && player.getPlaybackState() == Player.STATE_ENDED) {
+ player.seekTo(0);
+ }
+ if (exoplayerView != null) {
+ exoplayerView.setPausedModifier(false);
+ }
+ });
+
+ //Handling the pauseButton click event
+ playerControlView.findViewById(R.id.exo_pause).setOnClickListener(v -> {
+ if (exoplayerView != null) {
+ exoplayerView.setPausedModifier(true);
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (exoplayerView != null) {
+ exoplayerView.syncPlayerState();
+ exoplayerView.registerFullScreenDelegate(this);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ player.setPlayWhenReady(false);
+ if (exoplayerView != null) {
+ exoplayerView.registerFullScreenDelegate(null);
+ }
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (hasFocus) {
+ playerControlView.postDelayed(this::hideSystemUI, 200);
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if ((keyCode == KeyEvent.KEYCODE_BACK)) {
+ if (exoplayerView != null) {
+ exoplayerView.setFullscreen(false);
+ return false;
+ }
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ private void togglePlayerControlVisibility() {
+ if (playerControlView.isVisible()) {
+ playerControlView.hide();
+ } else {
+ playerControlView.show();
+ }
+ }
+
+ /**
+ * Enables regular immersive mode.
+ */
+ private void hideSystemUI() {
+ View decorView = getWindow().getDecorView();
+ decorView.setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_IMMERSIVE
+ // Set the content to appear under the system bars so that the
+ // content doesn't resize when the system bars hide and show.
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ // Hide the nav bar and status bar
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_FULLSCREEN);
+ }
+
+ /**
+ * Shows the system bars by removing all the flags
+ * except for the ones that make the content appear under the system bars.
+ */
+ private void showSystemUI() {
+ View decorView = getWindow().getDecorView();
+ decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ }
+
+ @Override
+ public void closeFullScreen() {
+ finish();
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java
index a6cd1c4f24..764323ef54 100644
--- a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java
+++ b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java
@@ -136,9 +136,9 @@ private void updateShutterViewVisibility() {
* @param player The {@link ExoPlayer} to use.
*/
public void setPlayer(ExoPlayer player) {
- if (this.player == player) {
- return;
- }
+ // if (this.player == player) {
+ // return;
+ // }
if (this.player != null) {
this.player.removeListener(componentListener);
clearVideoView();
diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
index 3dccad9398..dee050f9c7 100644
--- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
+++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
@@ -2,6 +2,7 @@
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.content.Intent;
import android.app.ActivityManager;
import android.content.Context;
import android.media.AudioManager;
@@ -94,6 +95,7 @@
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
@@ -132,6 +134,9 @@ class ReactExoplayerView extends FrameLayout implements
DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
}
+ private static Map instances = new HashMap<>();
+ private FullScreenDelegate fullScreenDelegate;
+
private final VideoEventEmitter eventEmitter;
private final ReactExoplayerConfig config;
private final DefaultBandwidthMeter bandwidthMeter;
@@ -150,6 +155,8 @@ class ReactExoplayerView extends FrameLayout implements
private long resumePosition;
private boolean loadVideoStarted;
private boolean isFullscreen;
+ private String fullScreenOrientation;
+ private boolean isInFullscreen;
private boolean isInBackground;
private boolean isPaused;
private boolean isBuffering;
@@ -171,7 +178,7 @@ class ReactExoplayerView extends FrameLayout implements
private double maxHeapAllocationPercent = ReactExoplayerView.DEFAULT_MAX_HEAP_ALLOCATION_PERCENT;
private double minBackBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BACK_BUFFER_MEMORY_RESERVE;
private double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
- private Handler mainHandler;
+ // private Handler mainHandler;
// Props from React
private int backBufferDurationMs = DefaultLoadControl.DEFAULT_BACK_BUFFER_DURATION_MS;
@@ -254,7 +261,7 @@ public ReactExoplayerView(ThemedReactContext context, ReactExoplayerConfig confi
createViews();
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- themedReactContext.addLifecycleEventListener(this);
+ // themedReactContext.addLifecycleEventListener(this);
audioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(themedReactContext);
}
@@ -280,7 +287,7 @@ private void createViews() {
addView(exoPlayerView, 0, layoutParams);
- mainHandler = new Handler();
+ // mainHandler = new Handler();
}
@Override
@@ -303,7 +310,16 @@ protected void onDetachedFromWindow() {
@Override
public void onHostResume() {
if (!playInBackground || !isInBackground) {
- setPlayWhenReady(!isPaused);
+ // setPlayWhenReady(!isPaused);
+ if (isInFullscreen) {
+ if (player != null) {
+ exoPlayerView.setPlayer(player);
+ syncPlayerState();
+ }
+ isInFullscreen = false;
+ } else {
+ setPlayWhenReady(!isPaused);
+ }
}
isInBackground = false;
}
@@ -324,6 +340,7 @@ public void onHostDestroy() {
public void cleanUpResources() {
stopPlayback();
+ instances.remove(this.getId());
}
//BandwidthMeter.EventListener implementation
@@ -342,6 +359,29 @@ public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
}
}
+ public static ReactExoplayerView getViewInstance(Integer uid) {
+ return instances.get(uid);
+ }
+
+ public ExoPlayer getPlayer() {
+ return player;
+ }
+
+ public void syncPlayerState() {
+ if (player == null) return;
+ if (player.getPlaybackState() == Player.STATE_ENDED) {
+ // Try to get last frame displayed
+ player.seekTo(player.getDuration() - 200);
+ player.setPlayWhenReady(true);
+ } else {
+ player.setPlayWhenReady(!isPaused);
+ }
+ }
+
+ public void registerFullScreenDelegate(FullScreenDelegate delegate) {
+ this.fullScreenDelegate = delegate;
+ }
+
// Internal methods
/**
@@ -357,6 +397,16 @@ private void togglePlayerControlVisibility() {
}
}
+ private void showFullscreen() {
+ instances.put(this.getId(), this);
+ Intent intent = new Intent(getContext(), ExoPlayerFullscreenVideoActivity.class);
+ intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_EXO_PLAYER_VIEW_ID, this.getId());
+ intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_ORIENTATION, this.fullScreenOrientation);
+ getContext().startActivity(intent);
+ isInFullscreen = true;
+ }
+
+
/**
* Initializing Player control
*/
@@ -369,6 +419,7 @@ private void initializePlayerControl() {
playerControlView.setPlayer(player);
playerControlView.show();
playPauseControlContainer = playerControlView.findViewById(R.id.exo_play_pause_container);
+ playerControlView.findViewById(R.id.exo_fullscreen_button).setOnClickListener(v -> setFullscreen(true));
// Invoking onClick event for exoplayerView
exoPlayerView.setOnClickListener(new OnClickListener() {
@@ -495,11 +546,12 @@ public boolean shouldContinueLoading(long playbackPositionUs, long bufferedDurat
private void startBufferCheckTimer() {
Player player = this.player;
VideoEventEmitter eventEmitter = this.eventEmitter;
- Handler mainHandler = this.mainHandler;
+ // Handler mainHandler = this.mainHandler;
}
private void initializePlayer() {
+ themedReactContext.addLifecycleEventListener(this);
ReactExoplayerView self = this;
Activity activity = themedReactContext.getCurrentActivity();
// This ensures all props have been settled, to avoid async racing conditions.
@@ -858,9 +910,9 @@ private void stopPlayback() {
}
private void onStopPlayback() {
- if (isFullscreen) {
- setFullscreen(false);
- }
+ // if (isFullscreen) {
+ // setFullscreen(false);
+ // }
audioManager.abandonAudioFocus(this);
}
@@ -1735,32 +1787,39 @@ public void setFullscreen(boolean fullscreen) {
}
isFullscreen = fullscreen;
- Activity activity = themedReactContext.getCurrentActivity();
- if (activity == null) {
- return;
- }
- Window window = activity.getWindow();
- View decorView = window.getDecorView();
- int uiOptions;
+ // Activity activity = themedReactContext.getCurrentActivity();
+ // if (activity == null) {
+ // return;
+ // }
+ // 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
- | SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | SYSTEM_UI_FLAG_FULLSCREEN;
- } else {
- uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | SYSTEM_UI_FLAG_FULLSCREEN;
- }
+ // 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
+ // | SYSTEM_UI_FLAG_FULLSCREEN;
+ // }
eventEmitter.fullscreenWillPresent();
- decorView.setSystemUiVisibility(uiOptions);
+ // decorView.setSystemUiVisibility(uiOptions);
+ showFullscreen();
eventEmitter.fullscreenDidPresent();
} else {
- uiOptions = View.SYSTEM_UI_FLAG_VISIBLE;
+ // uiOptions = View.SYSTEM_UI_FLAG_VISIBLE;
eventEmitter.fullscreenWillDismiss();
- decorView.setSystemUiVisibility(uiOptions);
+ // decorView.setSystemUiVisibility(uiOptions);
eventEmitter.fullscreenDidDismiss();
+ if (fullScreenDelegate != null) {
+ fullScreenDelegate.closeFullScreen();
+ }
}
}
+ public void setFullscreenOrientation(String orientation) {
+ this.fullScreenOrientation = orientation;
+ }
public void setUseTextureView(boolean useTextureView) {
boolean finallyUseTextureView = useTextureView && this.drmUUID == null;
@@ -1838,4 +1897,8 @@ public void setControls(boolean controls) {
}
}
}
+
+ public interface FullScreenDelegate {
+ void closeFullScreen();
+ }
}
diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java
index 3744fcaea9..a7b7d4ef39 100644
--- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java
+++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java
@@ -71,6 +71,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager
-
+
+
+
+
+
diff --git a/android/src/main/res/layout/exo_player_fullscreen_video.xml b/android/src/main/res/layout/exo_player_fullscreen_video.xml
new file mode 100644
index 0000000000..49cb934767
--- /dev/null
+++ b/android/src/main/res/layout/exo_player_fullscreen_video.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
\ No newline at end of file