Describe the bug
TextureVideoView.prepareIfNeeded() crashes with a FileNotFoundException when the cached video file (/cache/rc_files/...mp4) is missing at the time MediaPlayer.setDataSource() is called. The setDataSource() call is not wrapped in any error handling, so the exception propagates up through the draw pass and becomes a fatal RuntimeException.
-
Environment
- Platform: Android
- SDK version: 9.22.2 (also checked 9.23.0 and 9.23.1 changelogs — no fix present)
- OS version: Android 15
- Android Studio version: Latest stable
- How widespread is the issue: Low occurrence so far — observed on one device during testing, but it's a race condition that could affect any device where the cached video file is evicted or fails to download before playback begins.
-
Debug logs that reproduce the issue
N/A — crash occurred in a QA build. Stack trace below.
-
Steps to reproduce, with a description of expected vs. actual behavior
Steps:
- Present a RevenueCat Paywall that includes a video component
- The video file is downloaded to the
rc_files cache directory
- Before/during playback initialization, the cached file becomes unavailable (OS cache eviction, incomplete download, etc.)
onSurfaceTextureAvailable fires, calling prepareIfNeeded()
player.setDataSource(context, uri) throws FileNotFoundException
Expected: The SDK handles the missing file gracefully — e.g., by catching the exception in prepareIfNeeded(), logging an error, and either retrying the download or showing the paywall without the video.
Actual: Unhandled FileNotFoundException propagates through the view draw pass and crashes the app.
-
Other information
Stack trace:
Fatal Exception: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
Caused by java.io.FileNotFoundException: /data/user/0/com.jazarimusic.voloco/cache/rc_files/87f783e76683df036c3fa1165d9303d17162b4c1e21a34192ed124aa9a783a28.mp4: open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:574)
at java.io.FileInputStream.<init>(FileInputStream.java:179)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1238)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1216)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1181)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1106)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1052)
at com.revenuecat.purchases.ui.revenuecatui.components.video.TextureVideoView.prepareIfNeeded(VideoView.kt:261)
at com.revenuecat.purchases.ui.revenuecatui.components.video.TextureVideoView.access$prepareIfNeeded(VideoView.kt:70)
at com.revenuecat.purchases.ui.revenuecatui.components.video.TextureVideoView$1.onSurfaceTextureAvailable(VideoView.kt:126)
at android.view.TextureView.getTextureLayer(TextureView.java:501)
at android.view.TextureView.draw(TextureView.java:431)
...
Suggested fix: Wrap the setDataSource() call in prepareIfNeeded() with the existing safely() helper, or add a targeted try-catch for IOException:
// Current (VideoView.kt ~line 261):
player.setDataSource(context, it)
// Suggested:
safely(
execute = { player.setDataSource(context, it) },
failureMessage = { e -> "Could not set data source: ${e.message}" }
)
Related issues:
- PW-1061 — ANRs from
TextureVideoView.release() (same component, different bug)
Additional context
The safely() wrapper already exists in VideoView.kt and is used for other MediaPlayer operations (e.g., muting audio), but is not applied to setDataSource(). The video component was introduced relatively recently in PR #2680 (Oct 2025).
Describe the bug
TextureVideoView.prepareIfNeeded()crashes with aFileNotFoundExceptionwhen the cached video file (/cache/rc_files/...mp4) is missing at the timeMediaPlayer.setDataSource()is called. ThesetDataSource()call is not wrapped in any error handling, so the exception propagates up through the draw pass and becomes a fatalRuntimeException.Environment
Debug logs that reproduce the issue
N/A — crash occurred in a QA build. Stack trace below.
Steps to reproduce, with a description of expected vs. actual behavior
Steps:
rc_filescache directoryonSurfaceTextureAvailablefires, callingprepareIfNeeded()player.setDataSource(context, uri)throwsFileNotFoundExceptionExpected: The SDK handles the missing file gracefully — e.g., by catching the exception in
prepareIfNeeded(), logging an error, and either retrying the download or showing the paywall without the video.Actual: Unhandled
FileNotFoundExceptionpropagates through the view draw pass and crashes the app.Other information
Stack trace:
Suggested fix: Wrap the
setDataSource()call inprepareIfNeeded()with the existingsafely()helper, or add a targeted try-catch forIOException:Related issues:
TextureVideoView.release()(same component, different bug)Additional context
The
safely()wrapper already exists inVideoView.ktand is used for otherMediaPlayeroperations (e.g., muting audio), but is not applied tosetDataSource(). The video component was introduced relatively recently in PR #2680 (Oct 2025).