diff --git a/packages/react-native-video/android/src/main/AndroidManifest.xml b/packages/react-native-video/android/src/main/AndroidManifest.xml index bb10a3f9..f79cac1a 100644 --- a/packages/react-native-video/android/src/main/AndroidManifest.xml +++ b/packages/react-native-video/android/src/main/AndroidManifest.xml @@ -1,10 +1,3 @@ - - - - diff --git a/packages/react-native-video/android/src/main/AndroidManifestNew.xml b/packages/react-native-video/android/src/main/AndroidManifestNew.xml index bb10a3f9..f79cac1a 100644 --- a/packages/react-native-video/android/src/main/AndroidManifestNew.xml +++ b/packages/react-native-video/android/src/main/AndroidManifestNew.xml @@ -1,10 +1,3 @@ - - - - diff --git a/packages/react-native-video/android/src/main/java/com/video/core/VideoManager.kt b/packages/react-native-video/android/src/main/java/com/video/core/VideoManager.kt index 0c4acb37..979f41a4 100644 --- a/packages/react-native-video/android/src/main/java/com/video/core/VideoManager.kt +++ b/packages/react-native-video/android/src/main/java/com/video/core/VideoManager.kt @@ -3,7 +3,6 @@ package com.video.core import androidx.annotation.OptIn import androidx.media3.common.util.UnstableApi import com.margelo.nitro.video.HybridVideoPlayer -import com.video.core.activities.FullscreenVideoViewActivity import com.video.view.VideoView import java.lang.ref.WeakReference @@ -13,16 +12,8 @@ object VideoManager { private val views = mutableMapOf>() // player -> list of nitroIds of views that are using this player private val players = mutableMapOf>() - // fullscreen activity id (hash code) -> weak FullscreenVideoViewActivity - private val fullscreenActivities = mutableMapOf>() fun maybePassPlayerToView(player: HybridVideoPlayer) { - // If we have fullscreen activity open, we don't want to move player from it - // Fullscreen activity will attach player to view after destroy - if (fullscreenActivities.isNotEmpty()) { - return - } - val views = players[player]?.mapNotNull { getVideoViewWeakReferenceByNitroId(it)?.get() } ?: return val latestView = views.lastOrNull() ?: return @@ -52,72 +43,54 @@ object VideoManager { players[player]?.add(view.nitroId) } - fun removeViewFromPlayer(view: VideoView, player: HybridVideoPlayer, moveToLatestView: Boolean = true) { + fun removeViewFromPlayer(view: VideoView, player: HybridVideoPlayer) { players[player]?.remove(view.nitroId) - if(moveToLatestView) maybePassPlayerToView(player) + + // If this was the last view using this player, clean up + if (players[player]?.isEmpty() == true) { + players.remove(player) + } else { + // If there are other views using this player, move to the latest one + maybePassPlayerToView(player) + } } fun registerPlayer(player: HybridVideoPlayer) { - players[player] = players.getOrDefault(player, mutableListOf()) + if (!players.containsKey(player)) { + players[player] = mutableListOf() + } } fun unregisterPlayer(player: HybridVideoPlayer) { - // clear player from all views - val views = players[player]?.mapNotNull { getVideoViewWeakReferenceByNitroId(it)?.get() } ?: return - - views.forEach { view -> - // We are destroying player, so we don't need to look for a new view - removeViewFromPlayer(view, player, moveToLatestView = false) - } - - // Clear player from views - views.forEach { - it.hybridPlayer = null - } - players.remove(player) } - fun registerFullscreenActivity(activity: FullscreenVideoViewActivity, id: Int) { - fullscreenActivities[id] = WeakReference(activity) + fun getPlayerByNitroId(nitroId: Int): HybridVideoPlayer? { + return players.keys.find { player -> + players[player]?.contains(nitroId) == true + } } - fun unregisterFullscreenActivity(id: Int, player: HybridVideoPlayer?, moveToLatestView: Boolean = true) { - fullscreenActivities.remove(id) - - if (player != null && moveToLatestView) { - maybePassPlayerToView(player) + fun updateVideoViewNitroId(oldNitroId: Int, newNitroId: Int, view: VideoView) { + // Remove old mapping + if (oldNitroId != -1) { + views.remove(oldNitroId) + + // Update player mappings + players.keys.forEach { player -> + players[player]?.let { nitroIds -> + if (nitroIds.remove(oldNitroId)) { + nitroIds.add(newNitroId) } + } + } + } + + // Add new mapping + views[newNitroId] = WeakReference(view) } fun getVideoViewWeakReferenceByNitroId(nitroId: Int): WeakReference? { return views[nitroId] } - - fun updateVideoViewNitroId(oldNitroId: Int, newNitroId: Int, view: VideoView) { - // Update view in views map - views.remove(oldNitroId) - views[newNitroId] = WeakReference(view) - - // Update view in players map - players.forEach { (_, nitroIds) -> - // replace old id with new id (keep order) - val index = nitroIds.indexOf(oldNitroId) - - if (index != -1) { - nitroIds[index] = newNitroId - } - } - - // Update view in fullscreen activities map - fullscreenActivities.forEach { (_, activity) -> - if (activity.get()?.videoViewNitroId == oldNitroId) { - activity.get()?.videoViewNitroId = newNitroId - } - } - } - - fun getPlayerByNitroId(nitroId: Int): HybridVideoPlayer? { - return players.entries.firstOrNull { it.value.contains(nitroId) }?.key - } } diff --git a/packages/react-native-video/android/src/main/java/com/video/core/activities/FullscreenVideoViewActivity.kt b/packages/react-native-video/android/src/main/java/com/video/core/activities/FullscreenVideoViewActivity.kt deleted file mode 100644 index 6c0ec012..00000000 --- a/packages/react-native-video/android/src/main/java/com/video/core/activities/FullscreenVideoViewActivity.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.video.core.activities - -import android.annotation.SuppressLint -import android.app.Activity -import android.app.PictureInPictureParams -import android.content.res.Configuration -import android.os.Build -import android.os.Bundle -import android.util.Log -import android.util.Rational -import android.view.View -import android.view.WindowInsets -import android.view.WindowInsetsController -import android.widget.ImageButton -import androidx.annotation.RequiresApi -import androidx.media3.common.util.UnstableApi -import androidx.media3.ui.PlayerView -import com.margelo.nitro.video.HybridVideoPlayer -import com.video.R -import com.video.core.VideoManager -import com.video.core.utils.PictureInPictureUtils.calculateAspectRatio -import com.video.core.utils.PictureInPictureUtils.calculateSourceRectHint -import com.video.view.VideoView -import java.lang.ref.WeakReference - -@UnstableApi -class FullscreenVideoViewActivity : Activity() { - private lateinit var container: View - lateinit var playerView: PlayerView - - var videoViewNitroId: Int = -1 - private var videoView: WeakReference? = null - - private lateinit var player: HybridVideoPlayer - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.fullscreen_video_view_activity) - container = findViewById(R.id.fullscreen_container) - playerView = findViewById(R.id.player_view) - - try { - videoViewNitroId = intent.getIntExtra("nitroId", -1) - - if (videoViewNitroId == -1) throw Exception("nitroId not found") - - videoView = VideoManager.getVideoViewWeakReferenceByNitroId(videoViewNitroId) - - player = VideoManager.getPlayerByNitroId(videoViewNitroId) - ?: throw Exception("Player not found") - - player.moveToFullscreenActivity(this) - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val params = PictureInPictureParams.Builder() - .setAutoEnterEnabled(videoView?.get()?.autoEnterPictureInPicture == true) - .setSourceRectHint(calculateSourceRectHint(playerView)) - .setAspectRatio(calculateAspectRatio(playerView)) - .build() - - setPictureInPictureParams(params) - } - } catch (error: Error) { - Log.e("ReactNativeVideo - FullscreenVideoViewActivity", error.message, error) - finish() - return - } - } - - override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) { - super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) - - if (isInPictureInPictureMode) { - playerView.useController = false - } else { - playerView.useController = videoView?.get()?.useController == true - } - } - - override fun onPostCreate(savedInstanceState: Bundle?) { - super.onPostCreate(savedInstanceState) - setupFullScreenButton() - playerView.setShowSubtitleButton(true) - hideSystemUI() - } - - override fun onDestroy() { - super.onDestroy() - finish() - } - - override fun finish() { - super.finish() - VideoManager.unregisterFullscreenActivity(hashCode(), player) - videoView?.get()?.exitFullscreen() - } - - @SuppressLint("PrivateResource") - private fun setupFullScreenButton() { - playerView.setFullscreenButtonClickListener { _ -> - finish() - } - - // We need to manually change icon, as we are using separate PlayerView in fullscreen activity - val button = playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen) - button.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_exit) - } - - @Suppress("DEPRECATION") - private fun hideSystemUI() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - container.fitsSystemWindows = false - container.windowInsetsController?.let { controller -> - controller.hide(WindowInsets.Type.systemBars()) - controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } - } else { - window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - or View.SYSTEM_UI_FLAG_LAYOUT_STABLE - or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - or View.SYSTEM_UI_FLAG_FULLSCREEN) - } - } -} diff --git a/packages/react-native-video/android/src/main/java/com/video/core/fragments/FullscreenVideoFragment.kt b/packages/react-native-video/android/src/main/java/com/video/core/fragments/FullscreenVideoFragment.kt new file mode 100644 index 00000000..35d4eb2f --- /dev/null +++ b/packages/react-native-video/android/src/main/java/com/video/core/fragments/FullscreenVideoFragment.kt @@ -0,0 +1,231 @@ +package com.video.core.fragments + +import android.annotation.SuppressLint +import android.content.res.Configuration +import android.os.Build +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowInsets +import android.view.WindowInsetsController +import android.widget.FrameLayout +import android.widget.ImageButton +import androidx.activity.OnBackPressedCallback +import androidx.annotation.OptIn +import androidx.core.view.isVisible +import androidx.fragment.app.Fragment +import androidx.media3.common.util.UnstableApi +import com.video.core.utils.PictureInPictureUtils.createPictureInPictureParams +import com.video.view.VideoView +import java.util.UUID + +@OptIn(UnstableApi::class) +class FullscreenVideoFragment(private val videoView: VideoView) : Fragment() { + val id: String = UUID.randomUUID().toString() + + private var container: FrameLayout? = null + private var originalPlayerParent: ViewGroup? = null + private var originalPlayerLayoutParams: ViewGroup.LayoutParams? = null + private var rootContentViews: List = listOf() + + // Back press callback to handle back navigation + private val backPressCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + videoView.exitFullscreen() + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + // Create a fullscreen container + this.container = FrameLayout(requireContext()).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + setBackgroundColor(android.graphics.Color.BLACK) + keepScreenOn = true + } + return this.container + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + // Register back press callback + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressCallback) + + enterFullscreenMode() + setupPlayerView() + hideSystemUI() + + // Update PiP params if supported + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + val params = createPictureInPictureParams(videoView) + requireActivity().setPictureInPictureParams(params) + } catch (_: Exception) {} + } + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + + // Handle PiP mode changes + val isInPictureInPictureMode = + requireActivity().isInPictureInPictureMode + + if (isInPictureInPictureMode) { + videoView.playerView.useController = false + } else { + videoView.playerView.useController = videoView.useController + } + } + + private fun enterFullscreenMode() { + // Store original parent and layout params + originalPlayerParent = videoView.playerView.parent as? ViewGroup + originalPlayerLayoutParams = videoView.playerView.layoutParams + + // Remove player from original parent + originalPlayerParent?.removeView(videoView.playerView) + + // Hide all root content views + val currentActivity = requireActivity() + val rootContent = currentActivity.window.decorView.findViewById(android.R.id.content) + rootContentViews = (0 until rootContent.childCount) + .map { rootContent.getChildAt(it) } + .filter { it.isVisible } + + rootContentViews.forEach { view -> + view.visibility = View.GONE + } + + // Add our fullscreen container to root + rootContent.addView(container, + ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + ) + } + + private fun setupPlayerView() { + // Add PlayerView to our container + container?.addView(videoView.playerView, + FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT + ) + ) + + videoView.playerView.setBackgroundColor(android.graphics.Color.BLACK) + videoView.playerView.setShutterBackgroundColor(android.graphics.Color.BLACK) + + // We need show controls in fullscreen + videoView.playerView.useController = true + + setupFullscreenButton() + videoView.playerView.setShowSubtitleButton(true) + } + + @SuppressLint("PrivateResource") + private fun setupFullscreenButton() { + videoView.playerView.setFullscreenButtonClickListener { _ -> + videoView.exitFullscreen() + } + + // Change icon to exit fullscreen + val button = videoView.playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen) + button?.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_exit) + } + + @Suppress("DEPRECATION") + private fun hideSystemUI() { + val currentActivity = requireActivity() + container?.let { container -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + container.fitsSystemWindows = false + container.windowInsetsController?.let { controller -> + controller.hide(WindowInsets.Type.systemBars()) + controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } + } else { + currentActivity.window.decorView.systemUiVisibility = ( + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + or View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_FULLSCREEN + ) + } + } + } + + @Suppress("DEPRECATION") + private fun restoreSystemUI() { + val currentActivity = requireActivity() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + container?.windowInsetsController?.show(WindowInsets.Type.systemBars()) + } else { + currentActivity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE + } + } + + fun exitFullscreen() { + // Remove back press callback since we're exiting + backPressCallback.remove() + + restoreSystemUI() + + if (videoView.useController == false) { + videoView.playerView.useController = false + } + + // Ensure PlayerView keeps black background when returning to normal mode + videoView.playerView.setBackgroundColor(android.graphics.Color.BLACK) + videoView.playerView.setShutterBackgroundColor(android.graphics.Color.BLACK) + + // Remove PlayerView from our container + container?.removeView(videoView.playerView) + + // Remove our container from root + val currentActivity = requireActivity() + val rootContent = currentActivity.window.decorView.findViewById(android.R.id.content) + rootContent.removeView(container) + + // Restore root content views + rootContentViews.forEach { it.visibility = View.VISIBLE } + rootContentViews = listOf() + + // Safely restore PlayerView to original parent + // First, ensure PlayerView is removed from any current parent + val currentParent = videoView.playerView.parent as? ViewGroup + currentParent?.removeView(videoView.playerView) + + // Now add it back to the original parent + originalPlayerParent?.addView(videoView.playerView, originalPlayerLayoutParams) + + // Remove this fragment + parentFragmentManager.beginTransaction() + .remove(this) + .commitAllowingStateLoss() + + // Notify VideoView that we've exited fullscreen + videoView.isInFullscreen = false + } + + override fun onDestroy() { + super.onDestroy() + + // Ensure we clean up properly if fragment is destroyed + if (videoView.isInFullscreen) { + exitFullscreen() + } + } +} diff --git a/packages/react-native-video/android/src/main/java/com/video/hybrids/videoplayer/HybridVideoPlayer.kt b/packages/react-native-video/android/src/main/java/com/video/hybrids/videoplayer/HybridVideoPlayer.kt index cc590df5..cb346a74 100644 --- a/packages/react-native-video/android/src/main/java/com/video/hybrids/videoplayer/HybridVideoPlayer.kt +++ b/packages/react-native-video/android/src/main/java/com/video/hybrids/videoplayer/HybridVideoPlayer.kt @@ -28,7 +28,6 @@ import com.margelo.nitro.core.Promise import com.video.core.LibraryError import com.video.core.PlayerError import com.video.core.VideoManager -import com.video.core.activities.FullscreenVideoViewActivity import com.video.core.player.OnAudioFocusChangedListener import com.video.core.recivers.AudioBecomingNoisyReceiver import com.video.core.utils.Threading.runOnMainThread @@ -295,15 +294,6 @@ class HybridVideoPlayer() : HybridVideoPlayerSpec() { } } - fun moveToFullscreenActivity(activity: FullscreenVideoViewActivity) { - VideoManager.registerFullscreenActivity(activity, activity.hashCode()) - - runOnMainThreadSync { - PlayerView.switchTargetView(playerPointer, currentPlayerView?.get(), activity.playerView) - currentPlayerView = WeakReference(activity.playerView) - } - } - override val memorySize: Long get() = allocator?.totalBytesAllocated?.toLong() ?: 0L diff --git a/packages/react-native-video/android/src/main/java/com/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt b/packages/react-native-video/android/src/main/java/com/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt index 96a0cfd3..3be49a1d 100644 --- a/packages/react-native-video/android/src/main/java/com/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt +++ b/packages/react-native-video/android/src/main/java/com/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt @@ -35,7 +35,7 @@ class HybridVideoViewViewManager(nitroId: Int): HybridVideoViewViewManagerSpec() } override fun exitFullscreen() { - throw LibraryError.MethodNotSupported("exitFullscreen") + videoView.get()?.exitFullscreen() } override fun enterPictureInPicture() { diff --git a/packages/react-native-video/android/src/main/java/com/video/view/VideoView.kt b/packages/react-native-video/android/src/main/java/com/video/view/VideoView.kt index 7223bdce..e5807ef9 100644 --- a/packages/react-native-video/android/src/main/java/com/video/view/VideoView.kt +++ b/packages/react-native-video/android/src/main/java/com/video/view/VideoView.kt @@ -2,7 +2,6 @@ package com.video.view import android.annotation.SuppressLint import android.content.Context -import android.content.Intent import android.graphics.Color import android.os.Build import android.util.AttributeSet @@ -22,7 +21,7 @@ import com.margelo.nitro.video.VideoViewEvents import com.video.core.LibraryError import com.video.core.VideoManager import com.video.core.VideoViewError -import com.video.core.activities.FullscreenVideoViewActivity +import com.video.core.fragments.FullscreenVideoFragment import com.video.core.fragments.PictureInPictureHelperFragment import com.video.core.utils.PictureInPictureUtils.canEnterPictureInPicture import com.video.core.utils.PictureInPictureUtils.createPictureInPictureParams @@ -108,6 +107,7 @@ class VideoView @JvmOverloads constructor( } private var rootContentViews: List = listOf() private var pictureInPictureHelperTag: String? = null + private var fullscreenFragmentTag: String? = null val applicationContent: ReactApplicationContext get() { @@ -136,10 +136,14 @@ class VideoView @JvmOverloads constructor( post(layoutRunnable) } + @SuppressLint("PrivateResource") private fun setupFullscreenButton() { playerView.setFullscreenButtonClickListener { _ -> enterFullscreen() } + + playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen) + ?.setImageResource(androidx.media3.ui.R.drawable.exo_ic_fullscreen_enter) } fun enterFullscreen() { @@ -147,25 +151,54 @@ class VideoView @JvmOverloads constructor( return } - isInFullscreen = true - - val intent = Intent(context, FullscreenVideoViewActivity::class.java) - intent.putExtra("nitroId", nitroId) + val currentActivity = applicationContent.currentActivity + if (currentActivity !is FragmentActivity) { + Log.e("ReactNativeVideo", "Current activity is not a FragmentActivity, cannot enter fullscreen") + return + } try { - val currentActivity = applicationContent.currentActivity - currentActivity?.startActivity(intent) + events.willEnterFullscreen?.let { it() } + + val fragment = FullscreenVideoFragment(this) + fullscreenFragmentTag = fragment.id + + currentActivity.supportFragmentManager.beginTransaction() + .add(fragment, fragment.id) + .commitAllowingStateLoss() + + isInFullscreen = true } catch (err: Exception) { - val debugMessage = "Failed to start fullscreen activity for nitroId: $nitroId" + val debugMessage = "Failed to start fullscreen fragment for nitroId: $nitroId" Log.e("ReactNativeVideo", debugMessage, err) } } @SuppressLint("PrivateResource") fun exitFullscreen() { - // Change fullscreen button icon back to enter fullscreen - playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen) - ?.setImageResource(androidx.media3.ui.R.drawable.exo_ic_fullscreen_enter) + if (!isInFullscreen) { + return + } + + events.willExitFullscreen?.let { it() } + + val currentActivity = applicationContent.currentActivity + fullscreenFragmentTag?.let { tag -> + (currentActivity as? FragmentActivity)?.let { activity -> + activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment -> + // The fragment will handle its own removal in exitFullscreen() + if (fragment is FullscreenVideoFragment) { + runOnMainThread { + fragment.exitFullscreen() + } + } + } + } + fullscreenFragmentTag = null + } + + // Change fullscreen button icon back to enter fullscreen and update callback + setupFullscreenButton() isInFullscreen = false } @@ -199,11 +232,28 @@ class VideoView @JvmOverloads constructor( } } + private fun removeFullscreenFragment() { + val currentActivity = applicationContent.currentActivity + fullscreenFragmentTag?.let { tag -> + (currentActivity as? FragmentActivity)?.let { activity -> + activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment -> + activity.supportFragmentManager.beginTransaction() + .remove(fragment) + .commitAllowingStateLoss() + } + } + fullscreenFragmentTag = null + } + } + fun hideRootContentViews() { // Remove playerView from parent // In PiP mode, we don't want to show the controller // Controls are handled by System if we have MediaSession playerView.useController = false + playerView.setBackgroundColor(Color.BLACK) + playerView.setShutterBackgroundColor(Color.BLACK) + (playerView.parent as? ViewGroup)?.removeView(playerView) val currentActivity = applicationContent.currentActivity ?: return @@ -225,6 +275,9 @@ class VideoView @JvmOverloads constructor( // Reset PlayerView settings playerView.useController = useController + playerView.setBackgroundColor(Color.BLACK) + playerView.setShutterBackgroundColor(Color.BLACK) + val currentActivity = applicationContent.currentActivity ?: return val rootContent = currentActivity.window.decorView.findViewById(android.R.id.content) rootContent.removeView(playerView) @@ -273,6 +326,7 @@ class VideoView @JvmOverloads constructor( // -------- View Lifecycle Methods -------- override fun onDetachedFromWindow() { removePipHelper() + removeFullscreenFragment() VideoManager.unregisterView(this) super.onDetachedFromWindow() } diff --git a/packages/react-native-video/android/src/main/res/layout/fullscreen_video_view_activity.xml b/packages/react-native-video/android/src/main/res/layout/fullscreen_video_view_activity.xml deleted file mode 100644 index 8e5cdd47..00000000 --- a/packages/react-native-video/android/src/main/res/layout/fullscreen_video_view_activity.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - -