expo-video 56.0.2 → 56.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/video/FullscreenPlayerActivity.kt +5 -3
  4. package/android/src/main/java/expo/modules/video/VideoModule.kt +3 -3
  5. package/android/src/main/java/expo/modules/video/managers/VideoManager.kt +5 -0
  6. package/android/src/main/java/expo/modules/video/utils/PictureInPictureHelperFragment.kt +25 -5
  7. package/build/VideoView.d.ts +21 -0
  8. package/build/VideoView.d.ts.map +1 -1
  9. package/build/VideoView.js +21 -0
  10. package/build/VideoView.js.map +1 -1
  11. package/expo-module.config.json +1 -1
  12. package/local-maven-repo/host/exp/exponent/expo.modules.video/{56.0.2/expo.modules.video-56.0.2-sources.jar → 56.1.0/expo.modules.video-56.1.0-sources.jar} +0 -0
  13. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0-sources.jar.md5 +1 -0
  14. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0-sources.jar.sha1 +1 -0
  15. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0-sources.jar.sha256 +1 -0
  16. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0-sources.jar.sha512 +1 -0
  17. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.aar +0 -0
  18. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.aar.md5 +1 -0
  19. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.aar.sha1 +1 -0
  20. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.aar.sha256 +1 -0
  21. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.aar.sha512 +1 -0
  22. package/local-maven-repo/host/exp/exponent/expo.modules.video/{56.0.2/expo.modules.video-56.0.2.module → 56.1.0/expo.modules.video-56.1.0.module} +22 -22
  23. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.module.md5 +1 -0
  24. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.module.sha1 +1 -0
  25. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.module.sha256 +1 -0
  26. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.module.sha512 +1 -0
  27. package/local-maven-repo/host/exp/exponent/expo.modules.video/{56.0.2/expo.modules.video-56.0.2.pom → 56.1.0/expo.modules.video-56.1.0.pom} +1 -1
  28. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.pom.md5 +1 -0
  29. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.pom.sha1 +1 -0
  30. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.pom.sha256 +1 -0
  31. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.1.0/expo.modules.video-56.1.0.pom.sha512 +1 -0
  32. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml +4 -4
  33. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.md5 +1 -1
  34. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha1 +1 -1
  35. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha256 +1 -1
  36. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha512 +1 -1
  37. package/package.json +4 -4
  38. package/prebuilds/output/debug/xcframeworks/ExpoVideo.tar.gz +0 -0
  39. package/prebuilds/output/release/xcframeworks/ExpoVideo.tar.gz +0 -0
  40. package/src/VideoView.tsx +21 -0
  41. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2-sources.jar.md5 +0 -1
  42. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2-sources.jar.sha1 +0 -1
  43. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2-sources.jar.sha256 +0 -1
  44. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2-sources.jar.sha512 +0 -1
  45. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.aar +0 -0
  46. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.aar.md5 +0 -1
  47. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.aar.sha1 +0 -1
  48. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.aar.sha256 +0 -1
  49. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.aar.sha512 +0 -1
  50. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.module.md5 +0 -1
  51. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.module.sha1 +0 -1
  52. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.module.sha256 +0 -1
  53. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.module.sha512 +0 -1
  54. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.pom.md5 +0 -1
  55. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.pom.sha1 +0 -1
  56. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.pom.sha256 +0 -1
  57. package/local-maven-repo/host/exp/exponent/expo.modules.video/56.0.2/expo.modules.video-56.0.2.pom.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,16 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 56.1.0 — 2026-05-06
14
+
15
+ ### 🎉 New features
16
+
17
+ - [Android] Implement `exitFullscreen` to fix `MethodUnsupportedException`. ([#41836](https://github.com/expo/expo/pull/41836) by [@mensonones](https://github.com/mensonones))
18
+
19
+ ### 🐛 Bug fixes
20
+
21
+ - Fix `PictureInPictureHelperFragment` crashes on restoration after process death. ([#45426](https://github.com/expo/expo/pull/45426) by [@behenate](https://github.com/behenate) and [@dive](https://github.com/dive))
22
+
13
23
  ## 56.0.2 — 2026-05-06
14
24
 
15
25
  _This version does not introduce any user-facing changes._
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'host.exp.exponent'
7
- version = '56.0.2'
7
+ version = '56.1.0'
8
8
 
9
9
  android {
10
10
  namespace "expo.modules.video"
11
11
  defaultConfig {
12
12
  versionCode 1
13
- versionName '56.0.2'
13
+ versionName '56.1.0'
14
14
  }
15
15
  }
16
16
 
@@ -86,7 +86,7 @@ class FullscreenPlayerActivity : Activity(), VideoManagerListener {
86
86
  videoPlayer?.hasBeenDisconnectedFromVideoView() // The video player is disconnected. We are only using the ExoPlayer it contained
87
87
  }
88
88
 
89
- VideoManager.registerFullscreenPlayerActivity(hashCode().toString(), this)
89
+ videoViewId?.let { VideoManager.registerFullscreenPlayerActivity(it, this) }
90
90
  VideoManager.registerListener(this)
91
91
  playerView.player?.let {
92
92
  val aspectRatio = calculatePiPAspectRatio(it.videoSize, playerView.width, playerView.height, videoView.contentFit)
@@ -180,9 +180,11 @@ class FullscreenPlayerActivity : Activity(), VideoManagerListener {
180
180
  captioningChangeListener = null
181
181
  }
182
182
 
183
- videoView.exitFullscreen()
183
+ if (::videoView.isInitialized) {
184
+ videoView.exitFullscreen()
185
+ }
184
186
  VideoManager.unregisterListener(this)
185
- VideoManager.unregisterFullscreenPlayerActivity(hashCode().toString())
187
+ videoViewId?.let { VideoManager.unregisterFullscreenPlayerActivity(it) }
186
188
  orientationHelper?.stopOrientationEventListener()
187
189
  }
188
190
 
@@ -420,9 +420,9 @@ private inline fun <reified T : VideoView> ViewDefinitionBuilder<T>.VideoViewCom
420
420
  AsyncFunction("enterFullscreen") { view: T ->
421
421
  view.enterFullscreen()
422
422
  }.runOnQueue(Queues.MAIN)
423
- AsyncFunction("exitFullscreen") {
424
- throw MethodUnsupportedException("exitFullscreen")
425
- }
423
+ AsyncFunction("exitFullscreen") { view: T ->
424
+ VideoManager.finishFullscreenPlayer(view.videoViewId)
425
+ }.runOnQueue(Queues.MAIN)
426
426
  AsyncFunction("startPictureInPicture") { view: T ->
427
427
  runWithPiPMisconfigurationSoftHandling(true) {
428
428
  view.enterPictureInPicture()
@@ -101,6 +101,11 @@ object VideoManager {
101
101
  fullscreenPlayerActivities.remove(id)
102
102
  }
103
103
 
104
+ fun finishFullscreenPlayer(id: String) {
105
+ val activityRef = fullscreenPlayerActivities[id]
106
+ activityRef?.get()?.finish()
107
+ }
108
+
104
109
  fun onVideoPlayerAttachedToView(videoPlayer: VideoPlayer, videoView: VideoView) {
105
110
  if (videoPlayersToVideoViews[videoPlayer]?.contains(videoView) == true) {
106
111
  return
@@ -1,5 +1,6 @@
1
1
  package expo.modules.video
2
2
 
3
+ import android.os.Bundle
3
4
  import androidx.fragment.app.Fragment
4
5
  import java.lang.ref.WeakReference
5
6
  import java.util.UUID
@@ -9,21 +10,40 @@ interface PictureInPictureFragmentListener {
9
10
  fun onPictureInPictureStop()
10
11
  }
11
12
 
12
- class PictureInPictureHelperFragment(listener: PictureInPictureFragmentListener) : Fragment() {
13
+ // Keep this fragment restorable after Android process death.
14
+ // https://github.com/expo/expo/issues/42878
15
+ // Related PiP refactor: https://github.com/expo/expo/issues/40157
16
+ class PictureInPictureHelperFragment() : Fragment() {
17
+ constructor(listener: PictureInPictureFragmentListener) : this() {
18
+ this.listener = WeakReference(listener)
19
+ }
20
+
13
21
  val id = "${PictureInPictureHelperFragment::class.java.simpleName}_${UUID.randomUUID()}"
14
- private val listener = WeakReference(listener)
22
+ private var listener: WeakReference<PictureInPictureFragmentListener>? = null
23
+
24
+ override fun onCreate(savedInstanceState: Bundle?) {
25
+ super.onCreate(savedInstanceState)
26
+
27
+ if (listener == null) {
28
+ parentFragmentManager
29
+ .beginTransaction()
30
+ .remove(this)
31
+ .commitAllowingStateLoss()
32
+ }
33
+ }
15
34
 
16
35
  fun release() {
17
- listener.clear()
36
+ listener?.clear()
37
+ listener = null
18
38
  }
19
39
 
20
40
  override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
21
41
  super.onPictureInPictureModeChanged(isInPictureInPictureMode)
22
42
 
23
43
  if (isInPictureInPictureMode) {
24
- listener.get()?.onPictureInPictureStart()
44
+ listener?.get()?.onPictureInPictureStart()
25
45
  } else {
26
- listener.get()?.onPictureInPictureStop()
46
+ listener?.get()?.onPictureInPictureStop()
27
47
  }
28
48
  }
29
49
  }
@@ -23,6 +23,27 @@ export declare class VideoView extends PureComponent<VideoViewProps> {
23
23
  enterFullscreen(): Promise<void>;
24
24
  /**
25
25
  * Exits fullscreen mode.
26
+ *
27
+ * > **Note:** On Android the JS runtime is paused when the `VideoView` is in fullscreen mode. Because of this `exitFullscreen` will only work when called from a native listener - see the example below.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * const ref = useRef<VideoView>()
32
+ * const player = useVideoPlayer(source)
33
+ *
34
+ * // This will work on all platforms
35
+ * useEventListener(player, 'playToEnd', () => {
36
+ * ref.current?.exitFullscreen();
37
+ * });
38
+ *
39
+ * // This will not work on Android
40
+ * const enterAndExit = useCallback(() => {
41
+ * setTimeout(() => {
42
+ * ref.current?.exitFullscreen()
43
+ * }, 5000)
44
+ * ref.current?.enterFullscreen()
45
+ * },[])
46
+ * ```
26
47
  */
27
48
  exitFullscreen(): Promise<void>;
28
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"VideoView.d.ts","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,aAAa,EAAa,MAAM,OAAO,CAAC;AAKjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAErD;AAED,qBAAa,SAAU,SAAQ,aAAa,CAAC,cAAc,CAAC;IAC1D;;OAEG;IACH,SAAS,iCAAoB;IAE7B;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC;;;;;;;;;OASG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5C;;;;;OAKG;IACG,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3C,MAAM,IAAI,SAAS;CASpB"}
1
+ {"version":3,"file":"VideoView.d.ts","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,aAAa,EAAa,MAAM,OAAO,CAAC;AAKjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAErD;AAED,qBAAa,SAAU,SAAQ,aAAa,CAAC,cAAc,CAAC;IAC1D;;OAEG;IACH,SAAS,iCAAoB;IAE7B;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC;;;;;;;;;OASG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5C;;;;;OAKG;IACG,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3C,MAAM,IAAI,SAAS;CASpB"}
@@ -28,6 +28,27 @@ export class VideoView extends PureComponent {
28
28
  }
29
29
  /**
30
30
  * Exits fullscreen mode.
31
+ *
32
+ * > **Note:** On Android the JS runtime is paused when the `VideoView` is in fullscreen mode. Because of this `exitFullscreen` will only work when called from a native listener - see the example below.
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * const ref = useRef<VideoView>()
37
+ * const player = useVideoPlayer(source)
38
+ *
39
+ * // This will work on all platforms
40
+ * useEventListener(player, 'playToEnd', () => {
41
+ * ref.current?.exitFullscreen();
42
+ * });
43
+ *
44
+ * // This will not work on Android
45
+ * const enterAndExit = useCallback(() => {
46
+ * setTimeout(() => {
47
+ * ref.current?.exitFullscreen()
48
+ * }, 5000)
49
+ * ref.current?.enterFullscreen()
50
+ * },[])
51
+ * ```
31
52
  */
32
53
  async exitFullscreen() {
33
54
  return await this.nativeRef.current?.exitFullscreen();
@@ -1 +1 @@
1
- {"version":3,"file":"VideoView.js","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,eAAe,EAAE,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAI5E;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,iBAAiB,CAAC,2BAA2B,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,OAAO,SAAU,SAAQ,aAA6B;IAC1D;;OAEG;IACH,SAAS,GAAG,SAAS,EAAO,CAAC;IAE7B;;OAEG;IACH,KAAK,CAAC,eAAe;QACnB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IACzD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACxD,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,qBAAqB;QACzB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC;IAC/D,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,oBAAoB;QACxB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAC9D,CAAC;IAED,MAAM;QACJ,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAErD,IAAI,sBAAsB,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,KAAK,aAAa,EAAE,CAAC;YACvE,OAAO,KAAC,sBAAsB,OAAK,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,GAAI,CAAC;QACtF,CAAC;QACD,OAAO,KAAC,eAAe,OAAK,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,GAAI,CAAC;IAC/E,CAAC;CACF;AAED,gFAAgF;AAChF,gEAAgE;AAChE,yEAAyE;AACzE,SAAS,WAAW,CAAC,MAA4B;IAC/C,IAAI,MAAM,YAAY,iBAAiB,CAAC,WAAW,EAAE,CAAC;QACpD,mBAAmB;QACnB,OAAO,MAAM,CAAC,yBAAyB,CAAC;IAC1C,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { ReactNode } from 'react';\nimport { PureComponent, createRef } from 'react';\n\nimport NativeVideoModule from './NativeVideoModule';\nimport NativeVideoView, { NativeTextureVideoView } from './NativeVideoView';\nimport type { VideoPlayer } from './VideoPlayer.types';\nimport type { VideoViewProps } from './VideoView.types';\n\n/**\n * Returns whether the current device supports Picture in Picture (PiP) mode.\n *\n * > **Note:** All major web browsers support Picture in Picture (PiP) mode except Firefox.\n * > For more information, see [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/API/Picture-in-Picture_API#browser_compatibility).\n * @returns A `boolean` which is `true` if the device supports PiP mode, and `false` otherwise.\n * @platform android\n * @platform ios\n * @platform web\n */\nexport function isPictureInPictureSupported(): boolean {\n return NativeVideoModule.isPictureInPictureSupported();\n}\n\nexport class VideoView extends PureComponent<VideoViewProps> {\n /**\n * A reference to the underlying native view. On web it is a reference to the HTMLVideoElement.\n */\n nativeRef = createRef<any>();\n\n /**\n * Enters fullscreen mode.\n */\n async enterFullscreen(): Promise<void> {\n return await this.nativeRef.current?.enterFullscreen();\n }\n\n /**\n * Exits fullscreen mode.\n */\n async exitFullscreen(): Promise<void> {\n return await this.nativeRef.current?.exitFullscreen();\n }\n\n /**\n * Enters Picture in Picture (PiP) mode. Throws an exception if the device does not support PiP.\n * > **Note:** Only one player can be in Picture in Picture (PiP) mode at a time.\n *\n * > **Note:** The `supportsPictureInPicture` property of the [config plugin](#configuration-in-app-config)\n * > has to be configured for the PiP to work.\n * @platform android\n * @platform ios\n * @platform web\n */\n async startPictureInPicture(): Promise<void> {\n return await this.nativeRef.current?.startPictureInPicture();\n }\n\n /**\n * Exits Picture in Picture (PiP) mode.\n * @platform android\n * @platform ios\n * @platform web\n */\n async stopPictureInPicture(): Promise<void> {\n return await this.nativeRef.current?.stopPictureInPicture();\n }\n\n render(): ReactNode {\n const { player, ...props } = this.props;\n const playerId = player ? getPlayerId(player) : null;\n\n if (NativeTextureVideoView && this.props.surfaceType === 'textureView') {\n return <NativeTextureVideoView {...props} player={playerId} ref={this.nativeRef} />;\n }\n return <NativeVideoView {...props} player={playerId} ref={this.nativeRef} />;\n }\n}\n\n// Temporary solution to pass the shared object ID instead of the player object.\n// We can't really pass it as an object in the old architecture.\n// Technically we can in the new architecture, but it's not possible yet.\nfunction getPlayerId(player: number | VideoPlayer): number | null {\n if (player instanceof NativeVideoModule.VideoPlayer) {\n // @ts-expect-error\n return player.__expo_shared_object_id__;\n }\n if (typeof player === 'number') {\n return player;\n }\n return null;\n}\n"]}
1
+ {"version":3,"file":"VideoView.js","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,eAAe,EAAE,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAI5E;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,iBAAiB,CAAC,2BAA2B,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,OAAO,SAAU,SAAQ,aAA6B;IAC1D;;OAEG;IACH,SAAS,GAAG,SAAS,EAAO,CAAC;IAE7B;;OAEG;IACH,KAAK,CAAC,eAAe;QACnB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IACzD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,KAAK,CAAC,cAAc;QAClB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACxD,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,qBAAqB;QACzB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC;IAC/D,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,oBAAoB;QACxB,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAC9D,CAAC;IAED,MAAM;QACJ,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAErD,IAAI,sBAAsB,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,KAAK,aAAa,EAAE,CAAC;YACvE,OAAO,KAAC,sBAAsB,OAAK,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,GAAI,CAAC;QACtF,CAAC;QACD,OAAO,KAAC,eAAe,OAAK,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,GAAI,CAAC;IAC/E,CAAC;CACF;AAED,gFAAgF;AAChF,gEAAgE;AAChE,yEAAyE;AACzE,SAAS,WAAW,CAAC,MAA4B;IAC/C,IAAI,MAAM,YAAY,iBAAiB,CAAC,WAAW,EAAE,CAAC;QACpD,mBAAmB;QACnB,OAAO,MAAM,CAAC,yBAAyB,CAAC;IAC1C,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { ReactNode } from 'react';\nimport { PureComponent, createRef } from 'react';\n\nimport NativeVideoModule from './NativeVideoModule';\nimport NativeVideoView, { NativeTextureVideoView } from './NativeVideoView';\nimport type { VideoPlayer } from './VideoPlayer.types';\nimport type { VideoViewProps } from './VideoView.types';\n\n/**\n * Returns whether the current device supports Picture in Picture (PiP) mode.\n *\n * > **Note:** All major web browsers support Picture in Picture (PiP) mode except Firefox.\n * > For more information, see [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/API/Picture-in-Picture_API#browser_compatibility).\n * @returns A `boolean` which is `true` if the device supports PiP mode, and `false` otherwise.\n * @platform android\n * @platform ios\n * @platform web\n */\nexport function isPictureInPictureSupported(): boolean {\n return NativeVideoModule.isPictureInPictureSupported();\n}\n\nexport class VideoView extends PureComponent<VideoViewProps> {\n /**\n * A reference to the underlying native view. On web it is a reference to the HTMLVideoElement.\n */\n nativeRef = createRef<any>();\n\n /**\n * Enters fullscreen mode.\n */\n async enterFullscreen(): Promise<void> {\n return await this.nativeRef.current?.enterFullscreen();\n }\n\n /**\n * Exits fullscreen mode.\n *\n * > **Note:** On Android the JS runtime is paused when the `VideoView` is in fullscreen mode. Because of this `exitFullscreen` will only work when called from a native listener - see the example below.\n *\n * @example\n * ```tsx\n * const ref = useRef<VideoView>()\n * const player = useVideoPlayer(source)\n *\n * // This will work on all platforms\n * useEventListener(player, 'playToEnd', () => {\n * ref.current?.exitFullscreen();\n * });\n *\n * // This will not work on Android\n * const enterAndExit = useCallback(() => {\n * setTimeout(() => {\n * ref.current?.exitFullscreen()\n * }, 5000)\n * ref.current?.enterFullscreen()\n * },[])\n * ```\n */\n async exitFullscreen(): Promise<void> {\n return await this.nativeRef.current?.exitFullscreen();\n }\n\n /**\n * Enters Picture in Picture (PiP) mode. Throws an exception if the device does not support PiP.\n * > **Note:** Only one player can be in Picture in Picture (PiP) mode at a time.\n *\n * > **Note:** The `supportsPictureInPicture` property of the [config plugin](#configuration-in-app-config)\n * > has to be configured for the PiP to work.\n * @platform android\n * @platform ios\n * @platform web\n */\n async startPictureInPicture(): Promise<void> {\n return await this.nativeRef.current?.startPictureInPicture();\n }\n\n /**\n * Exits Picture in Picture (PiP) mode.\n * @platform android\n * @platform ios\n * @platform web\n */\n async stopPictureInPicture(): Promise<void> {\n return await this.nativeRef.current?.stopPictureInPicture();\n }\n\n render(): ReactNode {\n const { player, ...props } = this.props;\n const playerId = player ? getPlayerId(player) : null;\n\n if (NativeTextureVideoView && this.props.surfaceType === 'textureView') {\n return <NativeTextureVideoView {...props} player={playerId} ref={this.nativeRef} />;\n }\n return <NativeVideoView {...props} player={playerId} ref={this.nativeRef} />;\n }\n}\n\n// Temporary solution to pass the shared object ID instead of the player object.\n// We can't really pass it as an object in the old architecture.\n// Technically we can in the new architecture, but it's not possible yet.\nfunction getPlayerId(player: number | VideoPlayer): number | null {\n if (player instanceof NativeVideoModule.VideoPlayer) {\n // @ts-expect-error\n return player.__expo_shared_object_id__;\n }\n if (typeof player === 'number') {\n return player;\n }\n return null;\n}\n"]}
@@ -8,7 +8,7 @@
8
8
  "publication": {
9
9
  "groupId": "host.exp.exponent",
10
10
  "artifactId": "expo.modules.video",
11
- "version": "56.0.2",
11
+ "version": "56.1.0",
12
12
  "repository": "local-maven-repo"
13
13
  }
14
14
  }
@@ -0,0 +1 @@
1
+ b19d3a35fa0e41fd0a8c871d44bc4a7764384bb0567be3301ade3bf0f38bbb26
@@ -0,0 +1 @@
1
+ 5e6c36390418bf2397ef0c6958e449df2888ea2dc501c0940b460b91a3bc926b12ff108d9f403a82d11eb8dfc92cca63775d13b676076c731b36d69fd86f602e
@@ -0,0 +1 @@
1
+ 85fe07cc17b0994ac6f5153b4c4dbe7dcfad8431
@@ -0,0 +1 @@
1
+ 79189f3872954514e9f41141ad53f5a3e4938d49e508a3c6517b047b49318f58
@@ -0,0 +1 @@
1
+ 3d81df8482e208324d976aab42f05eb33e590fb16784aeda7192dbf68962fe652c8d6c077fee34b57b34e25187e598f085e7d5c664d002fb1d0cba6cccd6f6d4
@@ -3,7 +3,7 @@
3
3
  "component": {
4
4
  "group": "host.exp.exponent",
5
5
  "module": "expo.modules.video",
6
- "version": "56.0.2",
6
+ "version": "56.1.0",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
@@ -24,13 +24,13 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.video-56.0.2.aar",
28
- "url": "expo.modules.video-56.0.2.aar",
29
- "size": 609543,
30
- "sha512": "0ebcd18b0c9da70da2febb01aecdeb16d8fea98c0685ade5a3183e0737927d5f6ddb9e9436cec1e433c2708f40935b269efc71a81f43a5c7ebf25d505c5288e3",
31
- "sha256": "51a8154f1d564a40822d0ffc39126e421ac38ce689ac146b30734c4637af8bdd",
32
- "sha1": "a5b013a8cac091f042b924bf297c435dca9ff9c7",
33
- "md5": "d9c62df77478ee617af4ed3188af5745"
27
+ "name": "expo.modules.video-56.1.0.aar",
28
+ "url": "expo.modules.video-56.1.0.aar",
29
+ "size": 618621,
30
+ "sha512": "3d81df8482e208324d976aab42f05eb33e590fb16784aeda7192dbf68962fe652c8d6c077fee34b57b34e25187e598f085e7d5c664d002fb1d0cba6cccd6f6d4",
31
+ "sha256": "79189f3872954514e9f41141ad53f5a3e4938d49e508a3c6517b047b49318f58",
32
+ "sha1": "85fe07cc17b0994ac6f5153b4c4dbe7dcfad8431",
33
+ "md5": "13acd757c3d2766e3ccbdd2e901dfc84"
34
34
  }
35
35
  ]
36
36
  },
@@ -127,13 +127,13 @@
127
127
  ],
128
128
  "files": [
129
129
  {
130
- "name": "expo.modules.video-56.0.2.aar",
131
- "url": "expo.modules.video-56.0.2.aar",
132
- "size": 609543,
133
- "sha512": "0ebcd18b0c9da70da2febb01aecdeb16d8fea98c0685ade5a3183e0737927d5f6ddb9e9436cec1e433c2708f40935b269efc71a81f43a5c7ebf25d505c5288e3",
134
- "sha256": "51a8154f1d564a40822d0ffc39126e421ac38ce689ac146b30734c4637af8bdd",
135
- "sha1": "a5b013a8cac091f042b924bf297c435dca9ff9c7",
136
- "md5": "d9c62df77478ee617af4ed3188af5745"
130
+ "name": "expo.modules.video-56.1.0.aar",
131
+ "url": "expo.modules.video-56.1.0.aar",
132
+ "size": 618621,
133
+ "sha512": "3d81df8482e208324d976aab42f05eb33e590fb16784aeda7192dbf68962fe652c8d6c077fee34b57b34e25187e598f085e7d5c664d002fb1d0cba6cccd6f6d4",
134
+ "sha256": "79189f3872954514e9f41141ad53f5a3e4938d49e508a3c6517b047b49318f58",
135
+ "sha1": "85fe07cc17b0994ac6f5153b4c4dbe7dcfad8431",
136
+ "md5": "13acd757c3d2766e3ccbdd2e901dfc84"
137
137
  }
138
138
  ]
139
139
  },
@@ -147,13 +147,13 @@
147
147
  },
148
148
  "files": [
149
149
  {
150
- "name": "expo.modules.video-56.0.2-sources.jar",
151
- "url": "expo.modules.video-56.0.2-sources.jar",
152
- "size": 74449,
153
- "sha512": "3422fda7424a36e1c6af681337714e50f66d90d5b6590e7c9e3dbc980bd600afb4722274ace35bd4aeccd6dad2d407503288d692beb76a5611529b0553c37400",
154
- "sha256": "05982abc4ebfb0fa45aec2c03dd97bf470528c583e8c6f4596cef0e1379e2711",
155
- "sha1": "9995fb7879340676a149460e17d3e7546c809816",
156
- "md5": "9dd6d6b479c33c4f7eeabef7b5449a54"
150
+ "name": "expo.modules.video-56.1.0-sources.jar",
151
+ "url": "expo.modules.video-56.1.0-sources.jar",
152
+ "size": 74742,
153
+ "sha512": "5e6c36390418bf2397ef0c6958e449df2888ea2dc501c0940b460b91a3bc926b12ff108d9f403a82d11eb8dfc92cca63775d13b676076c731b36d69fd86f602e",
154
+ "sha256": "b19d3a35fa0e41fd0a8c871d44bc4a7764384bb0567be3301ade3bf0f38bbb26",
155
+ "sha1": "ccd8650ee4d87fc0f6d9835bce077a8930139b44",
156
+ "md5": "78ea3c6217d3be86fae6a74044e45192"
157
157
  }
158
158
  ]
159
159
  }
@@ -0,0 +1 @@
1
+ 074b0bd7d0a1bd3c43b84f2a225e35a74947b25825bce54eabf1347844ac08a1
@@ -0,0 +1 @@
1
+ 9f16c82e2a3dc6aa16b4b367b6b7582cf65d66c5b86d3fc03b486c7ed07e9dffbbafe4dcb31d2f3c2a9c45ef0f5c6603d0b6db7e9a46f14be22f2f81ced13f49
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>host.exp.exponent</groupId>
11
11
  <artifactId>expo.modules.video</artifactId>
12
- <version>56.0.2</version>
12
+ <version>56.1.0</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.video</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -0,0 +1 @@
1
+ a355f6dd44bd50ac0584e6c37027541d9c3f8471
@@ -0,0 +1 @@
1
+ 961bb4397ca951d67796b7277bcc382a6c1d07128822af12b0755442407f0c16
@@ -0,0 +1 @@
1
+ 00e1e3d85fbfb31d1b0c84c5a2358c66cc5f2a01a8dba403b4f1a06dee6ba9f1979afe63de67c8adffaa9c23d0e7bb6bd159b3991ca704067cc3d2844d686d1a
@@ -3,11 +3,11 @@
3
3
  <groupId>host.exp.exponent</groupId>
4
4
  <artifactId>expo.modules.video</artifactId>
5
5
  <versioning>
6
- <latest>56.0.2</latest>
7
- <release>56.0.2</release>
6
+ <latest>56.1.0</latest>
7
+ <release>56.1.0</release>
8
8
  <versions>
9
- <version>56.0.2</version>
9
+ <version>56.1.0</version>
10
10
  </versions>
11
- <lastUpdated>20260506190020</lastUpdated>
11
+ <lastUpdated>20260506211919</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- df219bfdde2b97068799daacb80be111
1
+ 36c6585db5e3cffed3ef64b7c3d1a537
@@ -1 +1 @@
1
- 93df5b8a511b2cc6902b902884364d6449c31074
1
+ 45a4164a74710b6ced9c990eadd7efffa3c020ae
@@ -1 +1 @@
1
- 596f2ebc2299dfc8d0c2182285800f538f935c310bd5e5dc77e7ffb7f21b3fd5
1
+ a4ff45218e91155dca9f79bb41c8a790015df6b5c04c6fcd16f6294d63adb4be
@@ -1 +1 @@
1
- 85334ad31bebe41e3b160eb525bbe3582a5c92c270d5dc7ffdf1253c2368400a82093b9b27610d64d7b6dd07863de13fae3150826ccc2878ff178854a82888aa
1
+ ce5a9df5b04ac68a8517d138f1bef72b33c389539df5663cc8fb146bb0a885dcc5d706c49e2254a186bb8b7c20b74e278caf712a4538de4fe911b889251e915a
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-video",
3
3
  "title": "Expo Video",
4
- "version": "56.0.2",
4
+ "version": "56.1.0",
5
5
  "description": "A cross-platform, performant video component for React Native and Expo with Web support",
6
6
  "main": "build/index.js",
7
7
  "types": "build/index.d.ts",
@@ -24,15 +24,15 @@
24
24
  "devDependencies": {
25
25
  "@types/node": "^22.14.0",
26
26
  "@types/react": "~19.2.0",
27
- "expo-module-scripts": "56.0.1",
28
- "expo": "56.0.0-preview.4"
27
+ "expo": "56.0.0-preview.5",
28
+ "expo-module-scripts": "56.0.2"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "expo": "*",
32
32
  "react": "*",
33
33
  "react-native": "*"
34
34
  },
35
- "gitHead": "d2109c94206280625a070242b0cb6e2500357c46",
35
+ "gitHead": "a8ab3da510a34b7bdb2262aa9887d4f78b102280",
36
36
  "scripts": {
37
37
  "build": "expo-module build",
38
38
  "clean": "expo-module clean",
package/src/VideoView.tsx CHANGED
@@ -35,6 +35,27 @@ export class VideoView extends PureComponent<VideoViewProps> {
35
35
 
36
36
  /**
37
37
  * Exits fullscreen mode.
38
+ *
39
+ * > **Note:** On Android the JS runtime is paused when the `VideoView` is in fullscreen mode. Because of this `exitFullscreen` will only work when called from a native listener - see the example below.
40
+ *
41
+ * @example
42
+ * ```tsx
43
+ * const ref = useRef<VideoView>()
44
+ * const player = useVideoPlayer(source)
45
+ *
46
+ * // This will work on all platforms
47
+ * useEventListener(player, 'playToEnd', () => {
48
+ * ref.current?.exitFullscreen();
49
+ * });
50
+ *
51
+ * // This will not work on Android
52
+ * const enterAndExit = useCallback(() => {
53
+ * setTimeout(() => {
54
+ * ref.current?.exitFullscreen()
55
+ * }, 5000)
56
+ * ref.current?.enterFullscreen()
57
+ * },[])
58
+ * ```
38
59
  */
39
60
  async exitFullscreen(): Promise<void> {
40
61
  return await this.nativeRef.current?.exitFullscreen();
@@ -1 +0,0 @@
1
- 05982abc4ebfb0fa45aec2c03dd97bf470528c583e8c6f4596cef0e1379e2711
@@ -1 +0,0 @@
1
- 3422fda7424a36e1c6af681337714e50f66d90d5b6590e7c9e3dbc980bd600afb4722274ace35bd4aeccd6dad2d407503288d692beb76a5611529b0553c37400
@@ -1 +0,0 @@
1
- a5b013a8cac091f042b924bf297c435dca9ff9c7
@@ -1 +0,0 @@
1
- 51a8154f1d564a40822d0ffc39126e421ac38ce689ac146b30734c4637af8bdd
@@ -1 +0,0 @@
1
- 0ebcd18b0c9da70da2febb01aecdeb16d8fea98c0685ade5a3183e0737927d5f6ddb9e9436cec1e433c2708f40935b269efc71a81f43a5c7ebf25d505c5288e3
@@ -1 +0,0 @@
1
- db60d8c0fd558a281d646c3e6919795286d79573
@@ -1 +0,0 @@
1
- c46a947e24e67f8ea7f95f6c3bb2bb10af587dac75869ab39674604feda7c3e4
@@ -1 +0,0 @@
1
- c49d93efcd6c33820fe95f6afce0e227793e6d000805e73babc01c77018457f50908e47d500e1b80068b9ca4f896e87fdc4d76ea4cb5ac518dd313b83e9b1a0a
@@ -1 +0,0 @@
1
- 595accee4ab8387df3b33cb0220d8da697468b65
@@ -1 +0,0 @@
1
- 0af3cef3a39b07bdb4cce0398f5f7d07b8be40b29485456d6163a11bddcc2207
@@ -1 +0,0 @@
1
- 21076edb139657fda73467d3f099980f7090e8ef49e12ce8ca93ead0aaef7aefc94d609aefa860d61c29c75350f16808586881597762e0fa4fb692db735ffd33