Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android: Keeping Native splash screen shown where possible #666

Closed
jonathanex opened this issue Jan 3, 2025 · 4 comments
Closed

Android: Keeping Native splash screen shown where possible #666

jonathanex opened this issue Jan 3, 2025 · 4 comments
Assignees
Labels
feature request New feature or request

Comments

@jonathanex
Copy link

jonathanex commented Jan 3, 2025

Why it is needed?

Hi, thanks for this package, it's been really useful - I've got a question as to whether something would be possible...

We work with a range of clients and some of them provide full artwork for icons - whether that's gradient background, imagery, etc - rather than just a logo on a solid background.

So in those cases, if we set the bootsplash image to match the icon they've provided (with an asset designed to match all the safe areas for them), you'll get the effect where, on a device supporting dynamic icons:

  • You tap the icon, cropped to a circle, on your home screen
  • The Android transition happens, that circle icon goes to the center of the screen in the native splash screen
  • The Bootsplash replica of the splash screen starts. The icon stays the same size, but is no longer cropped in a circle.

And as different devices can do different crops of dynamic icons, obviously we can't just assume it'll always be a circle and change the fallback circle - and as far as I can tell, Android doesn't let you know the styling of the homescreen so you could match it.

Possible implementation

So my question is would it be possible - on Android 12+ devices with the SplashScreen API support, to maintain keep the native OS splash screen rather than use the replica in this package?

Looking at the Android SplashScreen API, there's a section in the docs for 'Keep the splash screen on screen for longer periods'.

This seem to use ViewTreeObserver.OnPreDrawListener and overriding so only changing that value when you're ready.

Would it be possible for Bootsplash to set that listener, and then the existing hide command for it be used to remove it?

Any versions of Android pre-12 could still fallback to the same behaviour as it does now, but anything more modern could then rely on the OS more without need for any tweaks for per-device quirks or future changes.

This would also enable use of the animated AVD icons quite nicely - as the animation could run and stay on its end frame.

I'm not hugely versed in native Android so it while it looks theoretically possible to me, there may well be a drawback or something I'm misunderstanding and it wouldn't be possible in practice. If it is, hopefully it's an idea of interest.

Thank you!

Code sample

No response

@jonathanex jonathanex added the feature request New feature or request label Jan 3, 2025
@zoontek
Copy link
Owner

zoontek commented Jan 5, 2025

Hi! I won't go that way again, let me explain.

react-native-bootsplash v4 did use AndroidX compat library and ViewTreeObserver.OnPreDrawListener until the app is ready. This has a huge cost: it "freezes" the UI thread until the JS is loaded, parsed, executed and BootSplash.hide() is finally called.

This creates a ton of issues (ex: #381, #418), largely ignored by Google (search for splashscreen on their issue tracker), so the compat library has been removed in v5.

So my question is would it be possible - on Android 12+ devices with the SplashScreen API support, to maintain keep the native OS splash screen rather than use the replica in this package?

Not without the bugs that come with it.

And as different devices can do different crops of dynamic icons, obviously we can't just assume it'll always be a circle and change the fallback circle - and as far as I can tell, Android doesn't let you know the styling of the homescreen so you could match it.

Actually, the mask shape and size is fixed and well-known, and the bootsplash CLI even warns you about it. If you set a maximum value of 192dp, the logo will never be cropped:

splash-screen-icon-dimensions

This would also enable use of the animated AVD icons quite nicely - as the animation could run and stay on its end frame.

This has very little interest as it's not cross-platform. useHideAnimation works on Android, iOS and web.

@jonathanex
Copy link
Author

jonathanex commented Jan 6, 2025

Hey,

Thanks for replying!

Just for a bit of explanation of why this came up:

Actually, the mask shape and size is fixed and well-known, and the bootsplash CLI even warns you about it. If you set a maximum value of 192dp, the logo will never be cropped:

We did try working with this - but the problem came from when the logo is more a 'full art' style, where the background is integral (think how some game icons tend to be like that rather than traditional logos), rather than something with transparency that sits on the background, you still have a slightly jarring effect. (This came from trying to use their existing icon artwork as we were migrating to the new version of Bootsplash, rather than providing new artwork specifically for it).

However, that aside...

react-native-bootsplash v4 did use AndroidX compat library and ViewTreeObserver.OnPreDrawListener until the app is ready. This has a huge cost: it "freezes" the UI thread until the JS is loaded, parsed, executed and BootSplash.hide() is finally called.

This creates a ton of issues (ex: #381, #418), largely ignored by Google (search for splashscreen on their issue tracker), so the compat library has been removed in v5.

All of this completely makes sense as to why this approach I suggested is a non-starter entirely - thanks for setting that out in detail.

Thanks again for looking into this - I'll work on a different route for the project that this came up from.

@zoontek
Copy link
Owner

zoontek commented Jan 6, 2025

We did try working with this - but the problem came from when the logo is more a 'full art' style, where the background is integral (think how some game icons tend to be like that rather than traditional logos), rather than something with transparency that sits on the background, you still have a slightly jarring effect. (This came from trying to use their existing icon artwork as we were migrating to the new version of Bootsplash, rather than providing new artwork specifically for it).

The mask is applied by android SplashScreen API, keeping the native splash would keep the logo cropped during all the launch sequence, so this would not be a fix. You need to compose with the API limitations here. An alternative would be to re-apply the mask on the recreated bootsplash (like AndroidX does, on its created android.View), but it's breaking and relying on the logo being too big / cropped is a bit weird?

Again, the limitation does not come from BootSplash, but from the SplashScreen API. If they don't provide smaller assets, we can't do much here.

@jonathanex
Copy link
Author

The mask is applied by android SplashScreen API, keeping the native splash would keep the logo cropped during all the launch sequence, so this would not be a fix. You need to compose with the API limitations here. An alternative would be to re-apply the mask on the recreated bootsplash (like AndroidX does, on its created android.View), but it's breaking and relying on the logo being too big / cropped is a bit weird?

Ah - we may give that a go, thanks for flagging that up. It'd definitely be something that's opt-in, rather than useful by default. It's fairly unique to our circumstance that's how we would want it to work - actually embracing the crop during both launch and this, because we'd designed the art around the crop, rather than the approach the CLI takes which I completely get would be better for most users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants