apache / cordova-android

Apache Cordova Android
https://cordova.apache.org/
Apache License 2.0
3.59k stars 1.52k forks source link

navigator.splashscreen.hide() issue in cordova-android v11.0.0 when AutoHideSplashScreen is true or app uses redirect #1463

Closed fquirin closed 1 year ago

fquirin commented 1 year ago

Bug Report

Problem

I recently updated Cordova and the Android platform plugin both to v11.0.0, adjusted my config.xml to use AndroidWindowSplashScreenAnimatedIcon, removed old splash screen entries (except the ones mentioned below) and made a clean build of my project (Node.js 14). My app was previously able to close the splash screen manually so I had AutoHideSplashScreen set to true, SplashScreenDelay set to 10000 and simply used navigator.splashscreen.hide() to close the splash screen when my app is ready (depending on the device and connection quality 1-4s). In the worst case it would close after 10s.

[Update] Further investigation shows that it either happens when AutoHideSplashScreen is true or when the inAppBrowser plugin is used for redirection before navigator.splashscreen.hide() is called.

What is expected to happen?

navigator.splashscreen.hide() is supposed to close the splash screen before SplashScreenDelay expires.

What does actually happen?

The splash screen always stays for the full SplashScreenDelay time.

Information

Command or Code

Set the SplashScreenDelay to 60s and call navigator.splashscreen.hide() after device-ready but while the splash screen is still showing.

Environment, Platform, Device

I've tested the Android Emulator with Android 12.1, (real) Samsung mobile with Android 8, (real) Samsung tablet with Android 11. Every device has the same issue.

Version information

Cordova: "Pure" Cordova v11.0.0 with Android platform v11.0.0, no Ionic, no Capacitor Windows 11, Android Studio 2021.2.1 Patch 1

Checklist

breautek commented 1 year ago

There is no plugin information provided so I'm guessing here.

This splashscreen plugin hasn't been updated for the new Android splashscreens and it will not be. The new android splashscreen is implemented directly into the core platform in cordova-android@11 instead.

If you are using cordova-android@11, but still is using v6.0.1 or earlier of this plugin, I can guess there is an issue where the plugin API is overriding the core platform API.

The android implementation inside this plugin will be removed in the next major, leaving only browser & windows implementations left. If you do not build for either of those 2 platforms, you can safely remove this plugin.

Otherwise, make sure you're using at least v6.0.2 of this plugin, which has updated rules to prevent installing the plugin implementation on cordova-android@11.

Let me know if this information helps.

fquirin commented 1 year ago

Sorry I guess I should probably move this issue to the cordova-android repository instead since I was referring to the current version of this "plugin" that you get when you use cordova-android@11 and don't explicitly install an older version (v7.0.0?). It just feels more appropriate to post it here since the change is still very fresh.

breautek commented 1 year ago

since I was referring to the current version of this "plugin" that you get when you use cordova-android@11

By this, I take it then you do not actually have cordova-plugin-splashscreen installed? Am I understanding correctly?

If that's the case, then it sounds like your configuration is correct and what you're describing sounds like a bug that needs to be investigated within cordova-android. I can transfer the issue to the appropriate repository.

fquirin commented 1 year ago

By this, I take it then you do not actually have cordova-plugin-splashscreen installed?

yes, sorry, I did not explicitly install it.

I can transfer the issue to the appropriate repository.

That would be great, ty!

bonjourjoel commented 1 year ago

navigator.splashscreen.hide() does not hide the splashscreen in cordova android 11.0.0

It doesn't work either if the plugin cordova-plugin-splashscreen is installed, or if it's not installed. It doesn't hide the splash screen if both cases.

bhandaribhumin commented 1 year ago

Hi @bonjourjoel @breautek Found some little delay and blink before splash screen hide and also taking 4-6 second to hide the splash screen.

https://user-images.githubusercontent.com/3336047/183149525-dd965af5-21af-440e-9f0d-0251b0243679.mov

.

ljudbane commented 1 year ago

Hello.

I can observe the same behaviour if i set <preference name="AutoHideSplashScreen" value="true" />. The call to navigator.splashscreen.hide() won't actually hide the splash screen. If i set the above preference to false, then it works.

Is this the intended behaviour? If so, then it would be nice if it was mentioned in docs (https://cordova.apache.org/docs/en/latest/core/features/splashscreen/index.html#navigatorsplashscreenhide).

erisu commented 1 year ago

It was an unintentional change.

There is no reason why it can not go back to the original behavior.

I created code changes locally that should revert to the original behavior, but have not been tested yet. I can push a branch and create a PR if you like to test.

Also, as a note, I still do not see a valid benefit for mixing the manual and automatic hiding.

For example, from the ticket description:

My app was previously able to close the splash screen manually so I had AutoHideSplashScreen set to true,SplashScreenDelay set to 10000 and simply used navigator.splashscreen.hide() to close the splash screen when my app is ready (depending on the device and connection quality 1-4s). In the worst case it would close after 10s.

If the app hits the 10-second worst-case scenario and you used Cordova to hide the splash screen, then what will the end user see? A white screen?

I was thinking in these more advanced scenarios, it is up to the app developer to control the timeout, from the app level. So in the above case, the 10 seconds countdown would be in the app's javascript code, and then when 10 seconds are reached, the app can decide what to do. For example, hide the splash screen and prepare and render a static "Failed To Fetch Data" screen or whatever warning.

As the changes were made, for supporting Android 12 Splash, I tried to support as many of the previous preferences as possible and tried to keep the original behavior. Some couldn't be retained perfectly, but as for the AutoHide preference, I was looking at it, as if it was used only for a simple use case. For example, a simple application that was designed to use primarily static HTML, and JS, and didn't require external data.

How everyone used these flags and mixed them was not something I was completely aware of.

bonjourjoel commented 1 year ago

@erisu Hi, I'm not mixing these flags. I'm using it with autoHide=false. And it's not working, as I mentioned earlier: navigator.splashscreen.hide() does not hide the splashscreen in cordova android 11.0.0

erisu commented 1 year ago

@bonjourjoel

I am seeing mixed reports.

Can you upload a minimum reproduction repo so that I can run a test?

When tested before release, the navigator.splashscreen.hide() method was working.

@ljudbane also said,

If i set the above preference to false, then it works.

And this is refering to the AutoHideSplashScreen preference flag.

Also, please create a new issue ticket. The issue you are reporting is about the method not working at all, even with AutoHideSplashScreen set to false. The original author's report is about AutoHideSplashScreen set to true for the purpose of mixing of the features, which is different.

fquirin commented 1 year ago

I've done some remote debugging of the app using Chrome and tried to call the hide function manually

When I tested this I set AutoHideSplashScreen to false and since the splash-screen never closed I had time to connect remotely and call the function manually -> no effect. So for me neither setting will make the hide function work.

There should be some clean Cordova test app to try this in a controlled environment right? Some template maybe?

If the app hits the 10-second worst-case scenario and you used Cordova to hide the splash screen, then what will the end user see? A white screen?

He will see that the app is actually still doing something like loading content XY (a screen that the dev might prefer to hide for a certain grace period) or he will se an error message. Now obviously one could add the hide function to every error path and add some manual time-outs etc ... or one could simply rely on the auto-close feature.

erisu commented 1 year ago

Please upload a minimum reproduction repo that shows the issue.

I am still unable to reproduce the issue.

My test project had used:

Config.xml

<preference name="AutoHideSplashScreen" value="false" />

index.js

document.addEventListener('deviceready', onDeviceReady, false);

function onDeviceReady() {
    // Cordova is now initialized. Have fun!

    console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
    document.getElementById('deviceready').classList.add('ready');

    console.log('10 seconds timeout has been set');
    setTimeout(function () {
        console.log('10 seconds has passed. I will now hide the splash screen.');
        navigator.splashscreen.hide();
    }, 10000);
}

Logcat

2022-08-17 12:16:19.427 8661-8661/com.cdv.cordovaTest I/chromium: [INFO:CONSOLE(27)] "Running cordova-android@11.0.0", source: https://localhost/js/index.js (27)
2022-08-17 12:16:19.427 8661-8661/com.cdv.cordovaTest I/chromium: [INFO:CONSOLE(30)] "10 seconds timeout has been set", source: https://localhost/js/index.js (30)
2022-08-17 12:16:19.432 8661-8661/com.cdv.cordovaTest D/PluginManager: postMessage: spinner
2022-08-17 12:16:29.428 8661-8661/com.cdv.cordovaTest I/chromium: [INFO:CONSOLE(32)] "10 seconds has passed. I will now hide the splash screen.", source: https://localhost/js/index.js (32)
2022-08-17 12:16:29.428 8661-8718/com.cdv.cordovaTest D/CordovaSplashScreenPlugin: navigator.splashscreen.hide() was called and now setting the keepOnScreen to false.
2022-08-17 12:16:29.428 8661-8718/com.cdv.cordovaTest D/CordovaSplashScreenPlugin: Splashscreen is hidden.

Video Reference

10-second-splash-screen.webm

Additional Notes

I added two additional log printout lines in SplashScreenPlugin.java which displays the last two lines in the adb logcat.

2022-08-17 12:16:29.428 8661-8718/com.cdv.cordovaTest D/CordovaSplashScreenPlugin: navigator.splashscreen.hide() was called and now setting the keepOnScreen to false.
2022-08-17 12:16:29.428 8661-8718/com.cdv.cordovaTest D/CordovaSplashScreenPlugin: Splashscreen is hidden.

This shows that the native side of the code, that can only be triggered by the .hide action was executed.

fquirin commented 1 year ago

So, I did some digging and built the "Hello World" app from scratch 🙂:

sudo npm install -g cordova@11.0.0
cordova create hello com.example.hello HelloWorld
cd hello
cordova platform add android@11.0.0

After setting up the config and adding the hide function to the device-ready event as seen above it was indeed working if AutoHideSplashScreen is false!

Then I asked myself what is the difference to my "real" app, installed a dozen plugins and ... it was still working 😅 . Finally I reviewed my initial code and remembered this in my onDeviceReady function: cordova.InAppBrowser.open("index.html", "_self");. It is a redirect to my actual starting-page (my default is start.html) and for reasons I can't remember I decided years ago to use InAppBrowser.open to do it. After that navigator.splashscreen.hide() is broken when called in the new onDeviceReady or anywhere else in my app.

When I replace cordova.InAppBrowser.open("index.html", "_self"); with window.location.href = "index.html"; it miraculously starts working again! The old version of splash-screen didn't really care so the same code worked fine for the last ~3-4 years 🤷‍♂️ .

bonjourjoel commented 1 year ago

@erisu After uninstalling and reinstalling a lot of things, and i don't remember what I did and how many times i did it, the splash screen hide() function works with cordova android 11. I believe there is something that prevents a smooth update from the previous version of cordova android, but whatever. Thanks for the reply.

S3nivus commented 1 year ago

Same issue here. I couldn't hide the splashscreen on Android after upgrading the platform to v11.0.0 In my case removing and adding back cordova-plugin-inappbrowser did the trick. Now works as inteded with AutoHideSplashScreen true or false. The plugin version is 5.0.0 both when removing and adding it back Hope this can help in any way

florian72810 commented 1 year ago

I also had a problem with hide() not working, regardless of AutoHideSplashScreen.

I found that installing cordova-plugin-splashscreen is the problem. Version 6.0.2 is incompatible with Cordova-android 11. It is expected as it is not needed. But in my case, Cordova was still installing the last available version: 6.0.1. With this version, hide() is "broken".

I had to add plugin with a specific version: cordova plugin add cordova-plugin-splashscreen@6.0.2. Here, cordova cannot install a previous version for Android, it only adds for iOS. And everything works fine.

Hope this can help

erisu commented 1 year ago

@florian72810 If you are only building for Cordova-Android (11.x+) and Cordova-iOS (6.x+), you do not need to install cordova-plugin-splashscreen anymore.

The iOS portion of the plugin was already removed in version 6.0.0 as it was integrated into the core of cordova-ios@6.0.0.

ljudbane commented 1 year ago

When removin plugin completely from your project, make sure to remove both references in package.json file. One is npm package under devDependencies and another is under cordova.plugins. I had an issue where i removed only npm package from dependecies and plugin was still being added to android project because it was listed in cordova.plugins.

Removing all references to the plugin and re-creating android project/platform fixed the issue.

veronicatc commented 1 year ago

Same issue here. I couldn't hide the splashscreen on Android after upgrading the platform to v11.0.0 In my case removing and adding back cordova-plugin-inappbrowser did the trick. Now works as inteded with AutoHideSplashScreen true or false. The plugin version is 5.0.0 both when removing and adding it back Hope this can help in any way

@S3nivus worked for me. I had tried removing and adding the android platform before, no use. Splash screen would not hide. I then removed and added back the inappbrowser plugin, and also turned AutoHideSplashScreen to TRUE. Again removed and added the android platform after this. And then it worked. Then I changed AutoHideSplashScreen to FALSE, and it kept working, now hiding the splash with navigator.splashscreen.hide() ok.

mcastets commented 1 year ago

I'm having the same regression following an upgrade from cordova-android@10.1.1 to cordova-android@11.0.0: navigator.splashscreen.hide() no longer works when used with <preference name="AutoHideSplashScreen" value="true" />.

Notes:

varshas111 commented 1 year ago

I am having issue in splash screen after cordova android 11 upgrade. The splash screen is stretched now after adding preference tag

yeich commented 1 year ago

Currently i am facing an similar issue. Am I right, that i cant use "navigator.splashscreen.hide()" with "cordova-android@11.0.0"?

--

My Problem: After the "AutoHideSplashScreen" gets triggered, the screen remains white and my content will not load.

breautek commented 1 year ago

Am I right, that i cant use "navigator.splashscreen.hide()" with "cordova-android@11.0.0"?

navigor.splashscreen.hide is a supported API with Cordova Android 11 splashscreens, but the show API is no longer supported (cause Android splashscreens doesn't support reshowing the splashscreen).

When upgrading to cordova-android@11, make sure you also upgrade the splashscreen plugin. Older versions will conflict with cordova-android@11. If you only develop for android and iOS, the splashscreen plugin can be uninstalled as both of these platforms now include the splashscreen API as part of their core platform.

It appears that the issue has been identified and resolved by ensuring the splashscreen plugin is either upgraded or removed, so I'll be closing this ticket.

nyan-cat commented 1 year ago

Same bug here. Fresh new cordova 11 app -> splash screen doesn't go away. Is there a way to completely remove this useless "feature"?

lilGhosts commented 1 year ago

is there still no solution to this issue?

fquirin commented 1 year ago

For me it was resolved with what I found out here: https://github.com/apache/cordova-android/issues/1463#issuecomment-1219619306 Since it works on the clean test app, I'm assuming the remaining bugs are specific to individual setups.

bonjourjoel commented 1 year ago

is there still no solution to this issue?

Hi @xbox101xbox, I think this is an issue related to the update of cordova components. It doesn't happen if you create a new project, but if you update your former project, it can do this error.

I think the solution is to recreate the cordova project. Or at least to remove the related plugins and the platform android, and then add them back. That worked for me.

aesculus commented 1 year ago

I had the same issue. For me the hint from @S3nivus did the trick. Just updated the cordova-plugin-inappbrowser plugin.

ilyary commented 1 year ago

On my setup hide() method failed on page error, when I was calling navigator.splashscreen.hide(); from my error.html handling page.

However, I have noticed the SplashScreenPlugin has been initialised twice in this case.

I made a jump of faith: private boolean keepOnScreen = true; -> private static boolean keepOnScreen = true; in the plugin, and it worked!

Of course, it's not a real solution, but gives a spot of light what's going on here

KhAliMoh commented 11 months ago

I had the same problem while working with Polymer 2 and Cordova. At first, I made it work by adding the code navigator.splashscreen.hide() in the index file. But then, I needed to call it from my custom element called <main-app> after something loaded. When I tried adding the same code inside <main-app>, it didn't work. So, I tried using a setTimeout function with a 0-second delay, and it worked perfectly. I hope this information can help anyone who faces a similar problem.

setTimeout(()=> { navigator.splashscreen.hide() }, 0)