From ff1e24aaad179656af71443b3db3b9817a98eb92 Mon Sep 17 00:00:00 2001 From: Krzysztof Moch Date: Fri, 7 Jun 2024 13:54:14 +0200 Subject: [PATCH] fix: ensure view drop stop playback startup (#3875) --- .../exoplayer/ReactExoplayerView.java | 17 ++++++++++++++--- ios/Video/NowPlayingInfoCenterManager.swift | 4 ++-- ios/Video/RCTVideo.swift | 10 ++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index a4174891..6b54a9a4 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -258,6 +258,7 @@ public class ReactExoplayerView extends FrameLayout implements private long lastBufferDuration = -1; private long lastDuration = -1; + private boolean viewHasDropped = false; private void updateProgress() { if (player != null) { if (playerControlView != null && isPlayingAd() && controls) { @@ -375,6 +376,8 @@ public class ReactExoplayerView extends FrameLayout implements public void cleanUpResources() { stopPlayback(); themedReactContext.removeLifecycleEventListener(this); + releasePlayer(); + viewHasDropped = true; } //BandwidthMeter.EventListener implementation @@ -647,6 +650,9 @@ public class ReactExoplayerView extends FrameLayout implements Activity activity = themedReactContext.getCurrentActivity(); // This ensures all props have been settled, to avoid async racing conditions. mainRunnable = () -> { + if (viewHasDropped) { + return; + } try { if (player == null) { // Initialize core configuration and listeners @@ -658,7 +664,9 @@ public class ReactExoplayerView extends FrameLayout implements ExecutorService es = Executors.newSingleThreadExecutor(); es.execute(() -> { // DRM initialization must run on a different thread - + if (viewHasDropped) { + return; + } if (activity == null) { DebugLog.e(TAG, "Failed to initialize Player!, null activity"); eventEmitter.error("Failed to initialize Player!", new Exception("Current Activity is null!"), "1001"); @@ -667,12 +675,15 @@ public class ReactExoplayerView extends FrameLayout implements // Initialize handler to run on the main thread activity.runOnUiThread(() -> { + if (viewHasDropped) { + return; + } try { // Source initialization must run on the main thread initializePlayerSource(); } catch (Exception ex) { self.playerNeedsSource = true; - DebugLog.e(TAG, "Failed to initialize Player!"); + DebugLog.e(TAG, "Failed to initialize Player! 1"); DebugLog.e(TAG, ex.toString()); ex.printStackTrace(); self.eventEmitter.error(ex.toString(), ex, "1001"); @@ -684,7 +695,7 @@ public class ReactExoplayerView extends FrameLayout implements } } catch (Exception ex) { self.playerNeedsSource = true; - DebugLog.e(TAG, "Failed to initialize Player!"); + DebugLog.e(TAG, "Failed to initialize Player! 2"); DebugLog.e(TAG, ex.toString()); ex.printStackTrace(); eventEmitter.error(ex.toString(), ex, "1001"); diff --git a/ios/Video/NowPlayingInfoCenterManager.swift b/ios/Video/NowPlayingInfoCenterManager.swift index 2307e10b..6c416c72 100644 --- a/ios/Video/NowPlayingInfoCenterManager.swift +++ b/ios/Video/NowPlayingInfoCenterManager.swift @@ -61,11 +61,11 @@ class NowPlayingInfoCenterManager { return } - if let observer = observers[players.hashValue] { + if let observer = observers[player.hashValue] { observer.invalidate() } - observers.removeValue(forKey: players.hashValue) + observers.removeValue(forKey: player.hashValue) players.remove(player) if currentPlayer == player { diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index bf58d0c1..724f33c4 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -1241,10 +1241,19 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH // MARK: - Lifecycle override func removeFromSuperview() { + self._player?.replaceCurrentItem(with: nil) if let player = _player { player.pause() NowPlayingInfoCenterManager.shared.removePlayer(player: player) } + _playerItem = nil + _source = nil + _chapters = nil + _drm = nil + _textTracks = nil + _selectedTextTrackCriteria = nil + _selectedAudioTrackCriteria = nil + _presentingViewController = nil _player = nil _resouceLoaderDelegate = nil @@ -1252,6 +1261,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH #if USE_GOOGLE_IMA _imaAdsManager.releaseAds() + _imaAdsManager = nil #endif self.removePlayerLayer()