What happened?
Summary
PictureInPictureHelperFragment declares only a constructor that takes a VideoView. It has no public no-arg constructor. After process death or with developer setting "Don't keep activities" enabled, FragmentManager re-instantiates persisted fragments via reflection (clazz.getConstructor()), finds no no-arg constructor, and throws java.lang.NoSuchMethodException. The host activity fails to launch.
(verified the same code on master at android/src/main/java/com/twg/video/core/fragments/PictureInPictureHelperFragment.kt line 16)
Stack trace (production, deobfuscated)
java.lang.RuntimeException: Unable to start activity ComponentInfo{...MainActivity}:
androidx.fragment.app.Fragment$k: Unable to instantiate fragment
com.twg.video.core.fragments.PictureInPictureHelperFragment:
could not find Fragment constructor
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:4710)
...
Caused by: androidx.fragment.app.Fragment$k: Unable to instantiate fragment
com.twg.video.core.fragments.PictureInPictureHelperFragment:
could not find Fragment constructor
at androidx.fragment.app.FragmentFactory.instantiate (FragmentFactory.java:131)
at com.swmansion.rnscreens.fragment.restoration.RNScreensFragmentFactory.instantiate (RNScreensFragmentFactory.kt:11)
at androidx.fragment.app.FragmentState.instantiate (FragmentState.java:87)
at androidx.fragment.app.FragmentStateManager.<init> (FragmentStateManager.java:92)
at androidx.fragment.app.FragmentManager.restoreSaveStateInternal (FragmentManager.java:2849)
at androidx.fragment.app.FragmentManager.attachController (FragmentManager.java:3008)
at androidx.fragment.app.FragmentController.attachHost (FragmentController.java:117)
at androidx.fragment.app.FragmentActivity.lambda$init$3 (FragmentActivity.java:139)
at androidx.activity.contextaware.ContextAwareHelper.dispatchOnContextAvailable (ContextAwareHelper.kt:84)
at androidx.activity.ComponentActivity.onCreate (ComponentActivity.kt:331)
at androidx.fragment.app.FragmentActivity.onCreate (FragmentActivity.java:216)
at com.facebook.react.ReactActivity.onCreate (ReactActivity.java:60)
at com.shanttv.golive.MainActivity.onCreate (MainActivity.kt:24)
...
Caused by: java.lang.NoSuchMethodException:
com.twg.video.core.fragments.PictureInPictureHelperFragment.<init> []
at java.lang.Class.getConstructor0 (Class.java:3387)
at java.lang.Class.getConstructor (Class.java:2479)
at androidx.fragment.app.FragmentFactory.instantiate (FragmentFactory.java:121)
(Reproduces with or without react-native-screens — RNScreensFragmentFactory here just delegates to the default FragmentFactory.instantiate for non-RNScreens fragments.)
Impact
On our shipped 4.0.x line (~10k DAU app), this issue was the #1 fatal crash:
- 742 events / 428 distinct users in 7 days
- ~10.5% of users on the affected build
- 99% of crashes happen in the first second of session (consistent with crash-at-launch on restoration)
- Triggers any time the OS recreates the activity while a
<Video /> was previously mounted: low-memory background kill, "Don't keep activities", process death.
Root cause
PictureInPictureHelperFragment.kt:16:
class PictureInPictureHelperFragment(private val videoView: VideoView) : Fragment() {
Per the Android Fragment docs, all Fragment subclasses must have a public empty constructor — the framework needs it for state restoration. The fragment is added via:
// VideoView.kt, setupPipHelper()
val fragment = PictureInPictureHelperFragment(this)
it.supportFragmentManager.beginTransaction()
.add(fragment, fragment.id)
.commitAllowingStateLoss()
Because the fragment is committed (rather than retained out-of-band), Android persists its state across activity recreation and tries to rebuild it reflectively. There is no constructor for the framework to call, so launch fails.
Suggested fix
Give the fragment a no-arg primary constructor and treat the restored case as an orphan to be removed (the VideoView reference is gone after restoration, and React Native will re-mount its own helper when JS reattaches the <Video />):
class PictureInPictureHelperFragment() : Fragment() {
private var videoView: VideoView? = null
val id: String = UUID.randomUUID().toString()
constructor(videoView: VideoView) : this() {
this.videoView = videoView
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (videoView == null) {
// Restored after process death — the original VideoView is gone and React Native
// will re-mount its own helper. Drop this orphan instead of holding a dead fragment.
Handler(Looper.getMainLooper()).post {
if (isAdded) {
parentFragmentManager.beginTransaction().remove(this).commitAllowingStateLoss()
}
}
}
}
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode)
val videoView = videoView ?: return
// ... existing body unchanged ...
}
}
We're shipping this as a patch-package patch locally and can open a PR if helpful.
Steps to reproduce
- Mount a
<Video /> component on a screen.
- Background the app.
- Enable Developer Options → "Don't keep activities" (or wait for the OS to kill the process under memory pressure).
- Bring the app back to the foreground.
MainActivity.onCreate throws NoSuchMethodException and the app crashes immediately.
Reproduction repository
No response
react-native-video version
7.0.0-beta.9
react-native version
0.85.2 (new architecture enabled)
react-native-nitro-modules version
No response
Platforms
Android
OS version
Android 16
Device
Real device (Samsung SM-A336B and many other devices in production logs)
Architecture
New Architecture
Expo
No response
Last working version
No response
Media / source type
No response
What happened?
Summary
PictureInPictureHelperFragmentdeclares only a constructor that takes aVideoView. It has no public no-arg constructor. After process death or with developer setting "Don't keep activities" enabled,FragmentManagerre-instantiates persisted fragments via reflection (clazz.getConstructor()), finds no no-arg constructor, and throwsjava.lang.NoSuchMethodException. The host activity fails to launch.(verified the same code on
masteratandroid/src/main/java/com/twg/video/core/fragments/PictureInPictureHelperFragment.ktline 16)Stack trace (production, deobfuscated)
(Reproduces with or without
react-native-screens—RNScreensFragmentFactoryhere just delegates to the defaultFragmentFactory.instantiatefor non-RNScreens fragments.)Impact
On our shipped 4.0.x line (~10k DAU app), this issue was the #1 fatal crash:
<Video />was previously mounted: low-memory background kill, "Don't keep activities", process death.Root cause
PictureInPictureHelperFragment.kt:16:Per the Android Fragment docs, all
Fragmentsubclasses must have a public empty constructor — the framework needs it for state restoration. The fragment is added via:Because the fragment is committed (rather than retained out-of-band), Android persists its state across activity recreation and tries to rebuild it reflectively. There is no constructor for the framework to call, so launch fails.
Suggested fix
Give the fragment a no-arg primary constructor and treat the restored case as an orphan to be removed (the
VideoViewreference is gone after restoration, and React Native will re-mount its own helper when JS reattaches the<Video />):We're shipping this as a
patch-packagepatch locally and can open a PR if helpful.Steps to reproduce
<Video />component on a screen.MainActivity.onCreatethrowsNoSuchMethodExceptionand the app crashes immediately.Reproduction repository
No response
react-native-video version
7.0.0-beta.9
react-native version
0.85.2 (new architecture enabled)
react-native-nitro-modules version
No response
Platforms
Android
OS version
Android 16
Device
Real device (Samsung SM-A336B and many other devices in production logs)
Architecture
New Architecture
Expo
No response
Last working version
No response
Media / source type
No response