capacitor-plugins
capacitor-plugins copied to clipboard
@capacitor/splash-screen: Calling SplashScreen.hide() in background on Android causes crash
Bug Report
Plugin(s)
@capacitor/splash-screen
Capacitor Version
💊 Capacitor Doctor 💊
Latest Dependencies:
@capacitor/cli: 5.5.0
@capacitor/core: 5.5.0
@capacitor/android: 5.5.0
@capacitor/ios: 5.5.0
Installed Dependencies:
@capacitor/cli: 5.3.0
@capacitor/core: 5.3.0
@capacitor/android: 5.3.0
@capacitor/ios: 5.3.0
[info] Using Gemfile: RubyGems bundle installed
[success] iOS looking great! 👌
[success] Android looking great! 👌
Platform(s)
Android
Current Behavior
We've started seeing a couple of splash screen related crash reports in Firebase Crashlytics after a recent update to Capacitor 5.
Our investigation revealed it's related to the @capacitor/splash-screen
package.
The problem manifests itself when the app is backgrounded when the splash screen is still visible, and later the hide
method is called in the background.
Looking up the error message revealed the same issue was present in react-native-bootsplash
package. You can see this issue for additional technical details and applied fix.
Also it seems it's happening only for a specific subset of devices:
Stacktrace:
Fatal Exception: java.lang.NullPointerException
Attempt to invoke direct method 'void android.view.SurfaceControl.checkNotReleased()' on a null object reference
android.view.SurfaceControl.-$$Nest$mcheckNotReleased
android.view.SurfaceControl$Transaction.checkPreconditions (SurfaceControl.java:2798)
android.view.SurfaceControl$Transaction.hide (SurfaceControl.java:2950)
android.app.ActivityThread.syncTransferSplashscreenViewTransaction (ActivityThread.java:4200)
android.app.ActivityThread.-$$Nest$msyncTransferSplashscreenViewTransaction
android.app.ActivityThread$1.onDraw (ActivityThread.java:4177)
android.view.ViewTreeObserver.dispatchOnDraw (ViewTreeObserver.java:1132)
android.view.ViewRootImpl.draw (ViewRootImpl.java:4585)
android.view.ViewRootImpl.performDraw (ViewRootImpl.java:4368)
android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:3595)
android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:2354)
android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:9078)
android.view.Choreographer$CallbackRecord.run (Choreographer.java:1346)
android.view.Choreographer$CallbackRecord.run (Choreographer.java:1354)
android.view.Choreographer.doCallbacks (Choreographer.java:1005)
android.view.Choreographer.doFrame (Choreographer.java:936)
android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1322)
android.os.Handler.handleCallback (Handler.java:942)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loopOnce (Looper.java:227)
android.os.Looper.loop (Looper.java:327)
android.app.ActivityThread.main (ActivityThread.java:7995)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:942)
Expected Behavior
The app doesn't crash when splash screen hide
method is called in the background
Code Reproduction
https://github.com/jmartycak-rbi/capacitor-splash-screen-bug
Steps to reproduce in readme
Other Technical Details
n/a
Additional Context
https://github.com/zoontek/react-native-bootsplash/issues/381
This issue needs more information before it can be addressed. In particular, the reporter needs to provide a minimal sample app that demonstrates the issue. If no sample app is provided within 15 days, the issue will be closed.
Please see the Contributing Guide for how to create a Sample App.
Thanks! Ionitron 💙
Consider calling the hide
method within the callback of platform.ready
. You can refer to the following link for an example: GitHub - Ionic Conference App.
It also happens with the launchAutoHide
option and not explicitly calling the .hide()
method
SplashScreen: {
launchAutoHide: true,
launchShowDuration: 2000,
backgroundColor: "#F6F8F8",
androidScaleType: "CENTER_CROP",
splashFullScreen: true,
},
I tested the demo you provided on three different Android devices, and it performed well on all of them. To expedite the resolution of the issue you're encountering, it would be helpful if you could provide the Logcat log specific to the device where the problem occurs. This is especially important considering that not all development teams may have the OnePlus device for testing physical phones.
This is an Android 12 OS bug that was supposedly fixed on Android 13, but for some reason some devices with Android 13 (mostly Oppo/Oneplus) are still affected.
What react-native-bootsplash
has done is to remove the compatibility library, which is something we don't plan to do.
There must be something else I'm missing because the issue is on the OS, not on the compatibility library, so removing the compat library should not make any effect on Android 13 devices.
I've created a sample native app with just the splash code and no compatibility library and it still crash on Oppo devices.
The only thing I've found that makes the app to not crash is to not call setOnExitAnimationListener
, which will then disable the splash fade animation.
So we can add a feature to allow users to prevent the setOnExitAnimationListener
code from running if configured to do so, that will remove the animation but will prevent the crash on some devices.
in my react project:
capacitor.config.json
"plugins": {
"SplashScreen": {
"launchAutoHide": false
},
}
App.tsx
const timer = setTimeout(()=>{
SplashScreen.hide().catch((error) => console.error(error));
clearTimeout(timer);
},3000)
const App: React.FC = () => {
...
}
I only use it to avoid errors caused by Splash.hide().
@jcesarmobile Hi, react-native-bootsplash maintainer here.
The issue is caused by how they implement the way to keep the splash screen on screen.
They basically freeze the UI updates during the whole time the splash screen is visible.
Another thing you can try: Just after the splash screen is shown (with the AndroidX lib), try to lock the phone screen and unlock (put a timeout at 10s to hide the splash screen) 😅