1diff --git a/android/src/main/java/expo/modules/video/player/VideoPlayer.kt b/android/src/main/java/expo/modules/video/player/VideoPlayer.kt
2index 7ccce96..b6f30df 100644
3--- a/android/src/main/java/expo/modules/video/player/VideoPlayer.kt
4+++ b/android/src/main/java/expo/modules/video/player/VideoPlayer.kt
5@@ -265,6 +265,10 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
6 var keepScreenOnWhilePlaying by VideoPlayerKeepAwake(this, appContext)
8 private val playerListener = object : Player.Listener {
9+ override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
10+ emit("playbackRequestedChange", mapOf("isPlaybackRequested" to playWhenReady))
11+ }
12+
13 override fun onIsPlayingChanged(isPlaying: Boolean) {
14 this@VideoPlayer.playing = isPlaying
15 }
16diff --git a/ios/VideoPlayerObserver.swift b/ios/VideoPlayerObserver.swift
17index adf5820..ce69210 100644
18--- a/ios/VideoPlayerObserver.swift
19+++ b/ios/VideoPlayerObserver.swift
20@@ -46,6 +46,7 @@ private actor ObserverTaskManager {
21 protocol VideoPlayerObserverDelegate: AnyObject {
22 func onStatusChanged(player: AVPlayer, oldStatus: PlayerStatus?, newStatus: PlayerStatus, error: Exception?)
23 func onIsPlayingChanged(player: AVPlayer, oldIsPlaying: Bool?, newIsPlaying: Bool)
24+ func onPlaybackRequestedChanged(player: AVPlayer, requested: Bool)
25 func onRateChanged(player: AVPlayer, oldRate: Float?, newRate: Float)
26 func onVolumeChanged(player: AVPlayer, oldVolume: Float?, newVolume: Float)
27 func onPlayedToEnd(player: AVPlayer)
28@@ -66,6 +67,7 @@ protocol VideoPlayerObserverDelegate: AnyObject {
29 extension VideoPlayerObserverDelegate {
30 func onStatusChanged(player: AVPlayer, oldStatus: PlayerStatus?, newStatus: PlayerStatus, error: Exception?) {}
31 func onIsPlayingChanged(player: AVPlayer, oldIsPlaying: Bool?, newIsPlaying: Bool) {}
32+ func onPlaybackRequestedChanged(player: AVPlayer, requested: Bool) {}
33 func onRateChanged(player: AVPlayer, oldRate: Float?, newRate: Float) {}
34 func onVolumeChanged(player: AVPlayer, oldVolume: Float?, newVolume: Float) {}
35 func onPlayedToEnd(player: AVPlayer) {}
36@@ -497,6 +499,12 @@ class VideoPlayerObserver: VideoSourceLoaderListener {
37 }
39 private func onTimeControlStatusChanged(_ player: AVPlayer, _ change: NSKeyValueObservedChange<AVPlayer.TimeControlStatus>) {
40+ // Waiting (including evaluatingBufferingRate) preserves the native play request.
41+ let requested = player.timeControlStatus != .paused && player.status != .failed && player.currentItem?.status != .failed
42+ delegates.forEach { delegate in
43+ delegate.value?.onPlaybackRequestedChanged(player: player, requested: requested)
44+ }
45+
46 // iOS changes timeControlStatus after an error, so we need to check for errors.
47 if player.status == .failed || player.currentItem?.status == .failed {
48 isPlaying = false
49diff --git a/ios/VideoPlayer.swift b/ios/VideoPlayer.swift
50index 3c2fde4..ef43248 100644
51--- a/ios/VideoPlayer.swift
52+++ b/ios/VideoPlayer.swift
53@@ -396,6 +396,12 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
54 VideoManager.shared.setAppropriateAudioSessionOrWarn()
55 }
57+ func onPlaybackRequestedChanged(player: AVPlayer, requested: Bool) {
58+ if self.appContext != nil {
59+ self.emit(event: "playbackRequestedChange", payload: ["isPlaybackRequested": requested])
60+ }
61+ }
62+
63 func onRateChanged(player: AVPlayer, oldRate: Float?, newRate: Float) {
64 if #available(iOS 16.0, tvOS 16.0, *) {
65 if player.defaultRate != playbackRate {
66diff --git a/src/VideoPlayerEvents.types.ts b/src/VideoPlayerEvents.types.ts
67index c53b082..2d5fbcb 100644
68--- a/src/VideoPlayerEvents.types.ts
69+++ b/src/VideoPlayerEvents.types.ts
70@@ -11,6 +11,9 @@ import type {
71 * Handlers for events which can be emitted by the player.
72 */
73 export type VideoPlayerEvents = {
74+ /** Native play/pause intent, preserved while buffering or seeking. */
75+ playbackRequestedChange(payload: { isPlaybackRequested: boolean }): void;
76+
77 /**
78 * Handler for an event emitted when the status of the player changes.
79 */
80diff --git a/build/VideoPlayerEvents.types.d.ts b/build/VideoPlayerEvents.types.d.ts
81index 9c7eaea..25b8799 100644
82--- a/build/VideoPlayerEvents.types.d.ts
83+++ b/build/VideoPlayerEvents.types.d.ts
84@@ -3,6 +3,9 @@ import type { PlayerError, SubtitleTrack, VideoPlayerStatus, VideoSource, VideoT
85 * Handlers for events which can be emitted by the player.
86 */
87 export type VideoPlayerEvents = {
88+ /** Native play/pause intent, preserved while buffering or seeking. */
89+ playbackRequestedChange(payload: { isPlaybackRequested: boolean }): void;
90+
91 /**
92 * Handler for an event emitted when the status of the player changes.
93 */