diff --git a/android/src/main/java/com/brentvatne/common/api/Source.kt b/android/src/main/java/com/brentvatne/common/api/Source.kt index 60c2711b..e41761a4 100644 --- a/android/src/main/java/com/brentvatne/common/api/Source.kt +++ b/android/src/main/java/com/brentvatne/common/api/Source.kt @@ -57,9 +57,7 @@ class Source { } /** return true if this and src are equals */ - fun isEquals(source: Source): Boolean { - return this == source - } + fun isEquals(source: Source): Boolean = this == source /** Metadata to display in notification */ class Metadata { diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 7e5dc6bf..a4174891 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -258,29 +258,36 @@ public class ReactExoplayerView extends FrameLayout implements private long lastBufferDuration = -1; private long lastDuration = -1; + private void updateProgress() { + if (player != null) { + if (playerControlView != null && isPlayingAd() && controls) { + playerControlView.hide(); + } + long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100; + long duration = player.getDuration(); + long pos = player.getCurrentPosition(); + if (pos > duration) { + pos = duration; + } + + if (lastPos != pos + || lastBufferDuration != bufferedDuration + || lastDuration != duration) { + lastPos = pos; + lastBufferDuration = bufferedDuration; + lastDuration = duration; + eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos)); + } + } + } + private final Handler progressHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == SHOW_PROGRESS) { - if (player != null) { - if (playerControlView != null && isPlayingAd() && controls) { - playerControlView.hide(); - } - long pos = player.getCurrentPosition(); - long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100; - long duration = player.getDuration(); - - if (lastPos != pos - || lastBufferDuration != bufferedDuration - || lastDuration != duration) { - lastPos = pos; - lastBufferDuration = bufferedDuration; - lastDuration = duration; - eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos)); - } - msg = obtainMessage(SHOW_PROGRESS); - sendMessageDelayed(msg, Math.round(mProgressUpdateInterval)); - } + updateProgress(); + msg = obtainMessage(SHOW_PROGRESS); + sendMessageDelayed(msg, Math.round(mProgressUpdateInterval)); } } }; @@ -1337,6 +1344,7 @@ public class ReactExoplayerView extends FrameLayout implements break; case Player.STATE_ENDED: text += "ended"; + updateProgress(); eventEmitter.end(); onStopPlayback(); setKeepScreenOn(false); @@ -1614,6 +1622,7 @@ public class ReactExoplayerView extends FrameLayout implements // so we need to explicitly detect it. if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION && player.getRepeatMode() == Player.REPEAT_MODE_ONE) { + updateProgress(); eventEmitter.end(); } } diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index 379b19fd..bf58d0c1 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -312,7 +312,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH // MARK: - Progress - func sendProgressUpdate() { + func sendProgressUpdate(didEnd: Bool = false) { #if !USE_GOOGLE_IMA // If we dont use Ads and onVideoProgress is not defined we dont need to run this code guard onVideoProgress != nil else { return } @@ -334,11 +334,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH } let currentPlaybackTime = _player?.currentItem?.currentDate() let duration = CMTimeGetSeconds(playerDuration) - let currentTimeSecs = CMTimeGetSeconds(currentTime ?? .zero) + var currentTimeSecs = CMTimeGetSeconds(currentTime ?? .zero) - NotificationCenter.default.post(name: NSNotification.Name("RCTVideo_progress"), object: nil, userInfo: [ - "progress": NSNumber(value: currentTimeSecs / duration), - ]) + if currentTimeSecs > duration || didEnd { + currentTimeSecs = duration + } if currentTimeSecs >= 0 { #if USE_GOOGLE_IMA @@ -348,10 +348,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH } #endif onVideoProgress?([ - "currentTime": NSNumber(value: Float(currentTimeSecs)), + "currentTime": currentTimeSecs, "playableDuration": RCTVideoUtils.calculatePlayableDuration(_player, withSource: _source), - "atValue": NSNumber(value: currentTime?.value ?? .zero), - "currentPlaybackTime": NSNumber(value: NSNumber(value: Double(currentPlaybackTime?.timeIntervalSince1970 ?? 0 * 1000)).int64Value), + "atValue": currentTime?.value ?? .zero, + "currentPlaybackTime": NSNumber(value: Double(currentPlaybackTime?.timeIntervalSince1970 ?? 0 * 1000)).int64Value, "target": reactTag, "seekableDuration": RCTVideoUtils.calculateSeekableDuration(_player), ]) @@ -1570,6 +1570,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH @objc func handlePlayerItemDidReachEnd(notification: NSNotification!) { + sendProgressUpdate(didEnd: true) onVideoEnd?(["target": reactTag as Any]) #if USE_GOOGLE_IMA if notification.object as? AVPlayerItem == _player?.currentItem {