From 0104fbbbf366c2e5a5d9c80b14a4c7930e966947 Mon Sep 17 00:00:00 2001 From: Seyed Mostafa Hasani Date: Mon, 15 Jul 2024 13:34:49 +0330 Subject: [PATCH] chore(android): migrate FullScreenPlayerView to Kotlin (#3969) * Rename .java to .kt * chore(android): migrate FullScreenPlayerView to Kotlin * refactor: onBackPressed function * refactor: fullScreen button function * fix: lint error * chore: revert onBackPressed function --- .../exoplayer/FullScreenPlayerView.java | 136 ------------------ .../exoplayer/FullScreenPlayerView.kt | 131 +++++++++++++++++ 2 files changed, 131 insertions(+), 136 deletions(-) delete mode 100644 android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java create mode 100644 android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.kt diff --git a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java deleted file mode 100644 index b5d170a06b..0000000000 --- a/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.brentvatne.exoplayer; - -import android.annotation.SuppressLint; -import android.app.Dialog; -import android.content.Context; -import android.os.Handler; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.FrameLayout; -import android.widget.ImageButton; - -import androidx.activity.OnBackPressedCallback; -import androidx.media3.ui.LegacyPlayerControlView; - -import com.brentvatne.common.toolbox.DebugLog; - -import java.lang.ref.WeakReference; - -@SuppressLint("PrivateResource") -public class FullScreenPlayerView extends Dialog { - private final LegacyPlayerControlView playerControlView; - private final ExoPlayerView exoPlayerView; - private final ReactExoplayerView reactExoplayerView; - private ViewGroup parent; - private final FrameLayout containerView; - private final OnBackPressedCallback onBackPressedCallback; - private final Handler mKeepScreenOnHandler; - private final Runnable mKeepScreenOnUpdater; - - private static class KeepScreenOnUpdater implements Runnable { - private final static long UPDATE_KEEP_SCREEN_ON_FLAG_MS = 200; - private final WeakReference mFullscreenPlayer; - - KeepScreenOnUpdater(FullScreenPlayerView player) { - mFullscreenPlayer = new WeakReference<>(player); - } - - @Override - public void run() { - try { - FullScreenPlayerView fullscreenVideoPlayer = mFullscreenPlayer.get(); - if (fullscreenVideoPlayer != null) { - final Window window = fullscreenVideoPlayer.getWindow(); - if (window != null) { - boolean isPlaying = fullscreenVideoPlayer.exoPlayerView.isPlaying(); - if (isPlaying) { - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } else { - window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - } - fullscreenVideoPlayer.mKeepScreenOnHandler.postDelayed(this, UPDATE_KEEP_SCREEN_ON_FLAG_MS); - } - } catch (Exception ex) { - DebugLog.e("ExoPlayer Exception", "Failed to flag FLAG_KEEP_SCREEN_ON on fullscreeen."); - DebugLog.e("ExoPlayer Exception", ex.toString()); - } - } - } - - public FullScreenPlayerView(Context context, ExoPlayerView exoPlayerView, ReactExoplayerView reactExoplayerView, LegacyPlayerControlView playerControlView, OnBackPressedCallback onBackPressedCallback) { - super(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen); - this.playerControlView = playerControlView; - this.exoPlayerView = exoPlayerView; - this.reactExoplayerView = reactExoplayerView; - this.onBackPressedCallback = onBackPressedCallback; - containerView = new FrameLayout(context); - setContentView(containerView, generateDefaultLayoutParams()); - - mKeepScreenOnUpdater = new KeepScreenOnUpdater(this); - mKeepScreenOnHandler = new Handler(); - } - - @Override - public void onBackPressed() { - super.onBackPressed(); - onBackPressedCallback.handleOnBackPressed(); - } - - @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.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_exit); - imageButton.setContentDescription(getContext().getString(androidx.media3.ui.R.string.exo_controls_fullscreen_exit_description)); - parent.removeView(playerControlView); - containerView.addView(playerControlView, generateDefaultLayoutParams()); - } - - super.onStart(); - } - - @Override - protected void onStop() { - mKeepScreenOnHandler.removeCallbacks(mKeepScreenOnUpdater); - containerView.removeView(exoPlayerView); - parent.addView(exoPlayerView, generateDefaultLayoutParams()); - - if (playerControlView != null) { - ImageButton imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen); - imageButton.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_enter); - imageButton.setContentDescription(getContext().getString(androidx.media3.ui.R.string.exo_controls_fullscreen_enter_description)); - containerView.removeView(playerControlView); - parent.addView(playerControlView, generateDefaultLayoutParams()); - } - - parent.requestLayout(); - parent = null; - - super.onStop(); - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - - if (reactExoplayerView.getPreventsDisplaySleepDuringVideoPlayback()) { - mKeepScreenOnHandler.post(mKeepScreenOnUpdater); - } - } - - 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/FullScreenPlayerView.kt b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.kt new file mode 100644 index 0000000000..b66c1e88f4 --- /dev/null +++ b/android/src/main/java/com/brentvatne/exoplayer/FullScreenPlayerView.kt @@ -0,0 +1,131 @@ +package com.brentvatne.exoplayer + +import android.annotation.SuppressLint +import android.app.Dialog +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.FrameLayout +import android.widget.ImageButton +import androidx.activity.OnBackPressedCallback +import androidx.media3.ui.LegacyPlayerControlView +import com.brentvatne.common.toolbox.DebugLog +import java.lang.ref.WeakReference + +@SuppressLint("PrivateResource") +class FullScreenPlayerView( + context: Context, + private val exoPlayerView: ExoPlayerView, + private val reactExoplayerView: ReactExoplayerView, + private val playerControlView: LegacyPlayerControlView?, + private val onBackPressedCallback: OnBackPressedCallback +) : Dialog(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen) { + + private var parent: ViewGroup? = null + private val containerView = FrameLayout(context) + private val mKeepScreenOnHandler = Handler(Looper.getMainLooper()) + private val mKeepScreenOnUpdater = KeepScreenOnUpdater(this) + + private class KeepScreenOnUpdater(fullScreenPlayerView: FullScreenPlayerView) : Runnable { + private val mFullscreenPlayer = WeakReference(fullScreenPlayerView) + + override fun run() { + try { + val fullscreenVideoPlayer = mFullscreenPlayer.get() + if (fullscreenVideoPlayer != null) { + val window = fullscreenVideoPlayer.window + if (window != null) { + val isPlaying = fullscreenVideoPlayer.exoPlayerView.isPlaying + if (isPlaying) { + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + } + fullscreenVideoPlayer.mKeepScreenOnHandler.postDelayed(this, UPDATE_KEEP_SCREEN_ON_FLAG_MS) + } + } catch (ex: Exception) { + DebugLog.e("ExoPlayer Exception", "Failed to flag FLAG_KEEP_SCREEN_ON on fullscreen.") + DebugLog.e("ExoPlayer Exception", ex.toString()) + } + } + + companion object { + private const val UPDATE_KEEP_SCREEN_ON_FLAG_MS = 200L + } + } + + init { + setContentView(containerView, generateDefaultLayoutParams()) + } + override fun onBackPressed() { + super.onBackPressed() + onBackPressedCallback.handleOnBackPressed() + } + + override fun onStart() { + super.onStart() + parent = exoPlayerView.parent as ViewGroup? + parent?.removeView(exoPlayerView) + containerView.addView(exoPlayerView, generateDefaultLayoutParams()) + playerControlView?.let { + updateFullscreenButton(playerControlView, true) + parent?.removeView(it) + containerView.addView(it, generateDefaultLayoutParams()) + } + } + + override fun onStop() { + super.onStop() + mKeepScreenOnHandler.removeCallbacks(mKeepScreenOnUpdater) + containerView.removeView(exoPlayerView) + parent?.addView(exoPlayerView, generateDefaultLayoutParams()) + playerControlView?.let { + updateFullscreenButton(playerControlView, false) + containerView.removeView(it) + parent?.addView(it, generateDefaultLayoutParams()) + } + parent?.requestLayout() + parent = null + } + + private fun getFullscreenIconResource(isFullscreen: Boolean): Int { + return if (isFullscreen) { + androidx.media3.ui.R.drawable.exo_icon_fullscreen_exit + } else { + androidx.media3.ui.R.drawable.exo_icon_fullscreen_enter + } + } + + private fun updateFullscreenButton(playerControlView: LegacyPlayerControlView, isFullscreen: Boolean) { + val imageButton = playerControlView.findViewById(com.brentvatne.react.R.id.exo_fullscreen) + imageButton?.let { + val imgResource = getFullscreenIconResource(isFullscreen) + val desc = if (isFullscreen) { + context.getString(androidx.media3.ui.R.string.exo_controls_fullscreen_exit_description) + } else { + context.getString(androidx.media3.ui.R.string.exo_controls_fullscreen_enter_description) + } + imageButton.setImageResource(imgResource) + imageButton.contentDescription = desc + } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (reactExoplayerView.preventsDisplaySleepDuringVideoPlayback) { + mKeepScreenOnHandler.post(mKeepScreenOnUpdater) + } + } + + private fun generateDefaultLayoutParams(): FrameLayout.LayoutParams { + val layoutParams = FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT + ) + layoutParams.setMargins(0, 0, 0, 0) + return layoutParams + } +}