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

bug: SplashScreen.hide() doesn't work from remote server on Android #3485

Closed
simonhaenisch opened this issue Aug 28, 2020 · 10 comments
Closed

Comments

@simonhaenisch
Copy link
Contributor

simonhaenisch commented Aug 28, 2020

Bug Report

Capacitor Version

Latest Dependencies:

  @capacitor/cli: 2.4.0
  @capacitor/core: 2.4.0
  @capacitor/android: 2.4.0
  @capacitor/electron: 2.4.0
  @capacitor/ios: 2.4.0

Installed Dependencies:

  @capacitor/cli 2.4.0
  @capacitor/core 2.4.0
  @capacitor/android 2.4.0
  @capacitor/ios 2.4.0
  @capacitor/electron not installed

[success] Android looking great! 👌
  Found 0 Capacitor plugins for ios:
[success] iOS looking great! 👌

Platform(s)

Only Android, not iOS.

(Device is a Xiaomi Mi A2 Lite with Android 10)

Current Behavior

I have the following two things in capacitor.config.json:

{
  "plugins": {
    "SplashScreen": {
      "launchAutoHide": false
    }
  },
  "server": {
    "url": "https://caribbean-radio-tent-lol.trycloudflare.com"
  }
}

That (temporary) URL is created by cloudflared tunnel --url http://localhost:3333, i. e. that domain tunnels to a Stencil.js dev server that runs on my local machine (along with the tunnel). But the same thing happens with a deployed version of our app.

In our app-root.tsx we have

import { Plugins } from '@capacitor/core';

export class AppRoot {
  componentWillLoad() {
    await Plugins.SplashScreen.hide();
  }

  // ...
}

The hide call does not work after cold-booting the app... not sure whether it fails or just isn't called, the only log that might be relevant is

E/Capacitor/Console: File: https://caribbean-radio-tent-lol.trycloudflare.com/ - Line 1 - Msg: Uncaught TypeError: window.Capacitor.triggerEvent is not a function

but that one does not always come up in the logs.

When I'm in the stuck state, I can chrome://inspect the webapp just fine and it shows no errors. If I run await window.Capacitor.Plugins.SplashScreen.hide() in the dev-tools console, nothing happens. Here's a screenshot of some console outputs:

When going to the phone's home screen, then re-opening the app (from background, not cold-boot), the splash screen is gone.

When removing launchAutoHide from the capacitor config, I get this log:

SplashScreen was automatically hidden after the launch timeout. You should call `SplashScreen.hide()` as soon as your web app is loaded (or increase the timeout).Read more at https://capacitorjs.com/docs/apis/splash-screen#hiding-the-splash-screen

(and of course the splash screen disappears but it's definitely not a timeout issue because the app loads within less than a second)

Expected Behavior

Obviously, the splash screen should hide as soon as the SplashScreen.hide() call is made.

Other Technical Details

npm --version output: 6.14.5

node --version output: v14.5.0

Additional Context

Update: I just noticed that at least from what I can see in the console, Capacitor seems to think that it's running on web, not natively:

When I check the same thing on an iPhone, the platform is correctly determined as ios (and isNative is set):

@simonhaenisch
Copy link
Contributor Author

simonhaenisch commented Aug 28, 2020

Edit: After thinking that I couldn't reproduce this anymore, I found out what it is: it depends on whether I do a prod or dev build of our Stencil + Ionic app. In dev builds (non-minified) it does not happen, but in prod builds (minified) it does. By "it" I mean that Capacitor thinks the platform is web and therefore the splash screen can't hide.

I'll try to create a reproducible example using the ionic-stencil-conference-app tomorrow.

@simonhaenisch
Copy link
Contributor Author

Just a quick update: after debugging this further, the difference is that the prod build comes with a service worker and if I disable the service worker for the prod build, then the splash screen works as expected.

When bundling the web app into the app, the service worker fails to register which is why this doesn't happen when not using a remote server.

service worker error TypeError: Failed to register a ServiceWorker for scope ('http://localhost/')
with script ('http://localhost/sw.js'): An unknown error occurred when fetching the script.

Seems like the service worker isn't registered at all on iOS which is why the error only occurs on Android.

I'll do some more debugging later this week to narrow it down on what specifically is causing this in the service worker (but also wondering about general support of service workers in Capacitor).

@jcesarmobile
Copy link
Member

Capacitor code is not injected in service workers, if you want to inject it see #1655 (comment), but it only works on Android 7+ (SDK level 24+)

@simonhaenisch
Copy link
Contributor Author

Thanks for that link, that's exactly the problem 👍

@jcesarmobile do you have an idea for a way to block registration of the service worker in api levels 21-23? Or maybe you have any insight why this is only available since level 24? Is it because service workers aren't supported anyway? (which would be ideal 🤓)

@jcesarmobile
Copy link
Member

The ServiceWorkerController was introduced in API 24 and I don't think there is a support library for it to support older versions.
No idea if they are supported in older versions, supposedly it's a chromium feature and since the webview is updated, it should be supported too, but didn't try.

@simonhaenisch
Copy link
Contributor Author

simonhaenisch commented Sep 1, 2020

Ok thanks for the hints!

I've added the custom ServiceWorkerClient with shouldInterceptRequest override into our MainActivity but it doesn't seem to work. I've added Logger.debug(request.getUrl().toString()) into the method but nothing gets logged, i. e. the method never gets called (I've made sure the code runs though).

I've checked the ServiceWorkerController docs and it says

Sets the client to capture service worker related callbacks. A ServiceWorkerClient should be set before any service workers are active, e.g. a safe place is before any WebView instances are created or pages loaded.

so I've moved the block before the super.onCreate(savedInstanceState) call (in onCreate of MainActivity) and according to the logs it gets set first but still doesn't work 🤷🏻‍♂️

D/Capacitor: setting up shouldInterceptRequest
I/WebViewFactory: Loading com.google.android.webview version 85.0.4183.81 (code 418308183)
I/cr_LibraryLoader: Loaded native library version number "85.0.4183.81"

(first line is my custom log)

Is there maybe a repository of an app that uses this successfully?

BTW it does work the first time the app is launched but not anymore when restarting the app later, after the service worker is already registered.

@simonhaenisch
Copy link
Contributor Author

After a lot of debugging I think I finally figured out why shouldInterceptRequest doesn't work. The problem is that the service worker controller only allows to intercept real requests, not the ones that the service worker resolves from its cache. Since our service worker uses Workbox Precaching (precache manifest injection) for index.html, that wasn't working.

@bitflower
Copy link

@simonhaenisch I'm having the same issue (I guess). The web implementation is called. Is this what the error scenario looks like (debugger running on Android sim)?

image

@bitflower
Copy link

Ok, forget it. During a refactor the import of Splashscreen was changed to import directly from @capacitor/core instead of Plugins.

@ionitron-bot
Copy link

ionitron-bot bot commented Nov 11, 2022

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Nov 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants