Android OS nav and status bars toggling in and out on fullscreen PWA

Viewed 1428

My PWA's with "display": "fullscreen" have recently started misbehaving. The Android navbar and status bar keep re-appearing during play. The apps still launch in fullscreen normally, but every touch event re-shows the OS bottom navigation and top status bars briefly (as you would normally see in standalone display).

I don't believe this is related any code changes on my end, as some of my old, untouched PWA's have recently started behaving like this as well.

I'm on on a Pixel 5, Android 11, last updated within the last week.

Here is a short clip showing the issue.

3 Answers

I was investigating the same issue of ArcoMage HD (GitHub), an opensource React card game of mine.

The issue seems to be introduced by some very recent version (likely in Aug 2021 or shortly before it) of Android and Android Chrome (it'll be fine if you use the latest Chrome + an old Android).

This pretty annoying, bug-like behaviour makes "display": "fullscreen" totally unusable because when a user want to click a link/button, he will have to double tap the link/button! - the first tap cannot trigger the click of the link/button and can only make navigation bar and status bar appear, then the user must immediately tap the link/button for a second time, this time, the click or touch event is triggered.

Until Android/Chrome fixes this issue, a temporary fix that a PWA developer can do is: Use "display": "standalone", then either put a "toggle fullscreen" button (using Fullscreen API) somewhere, or check window.matchMedia("(display-mode: standalone)").matches and if it's true (meaning it's PWA) then make a transparent button covering the whole page, when the user clicks anywhere on the page, he actually clicks the button, which requests the fullscreen mode and deletes itself.

(Previously I thought we can use "display": "fullscreen" then enter fullscreen mode with the API when the app is loaded. Unfortunately, Chrome requires a user gesture to enter fullscreen)

For fullscreen toggling, you can use this snippet, or screenfull.js if you want better compatibility.

P.S. Chromium issue page: https://bugs.chromium.org/p/chromium/issues/detail?id=1232956

Good news: it's fixed in Chrome 95.0.4637.0 which will be available on Canary (unstable version) in the next few days (and we'll probably need to wait a little longer for the stable version to fix it)

23 Oct edit: Chrome (for Android) stable version is 95.x now

most of the answers are Java and Kotlin, Javascript is a little tricky, you can adopt this to pretty much any of the JS flavors/supersets. I am using the standalone and hiding the controls of the browser

I think the issue is that you have fullscreen, it will not work, you need standalone "display": "standalone"

  1. First detect if the PWA is running in standalone mode inside our application like this:
// on iOS Safari
window.navigator.standalone

// on Android Chrome 
// this is key for you..
window.matchMedia(
  '(display-mode: standalone)'
).matches

  1. Given various platforms, I recommend defining a start_url inside your manifest.json, it will save you in the long run :)

  2. Then both to display in fullscreen & remove native controls, add the display property with the value standalone (fullscreen won't work). your manifest should have something like this:

// manifest.json
{
  "name": "Tykt.org App",
  "display": "standalone",
  "start_url": "/?standalone=true"
}

Ensure your viewport-fit=cover is inside:

<meta name="viewport"
    content="width=device-width; initial-scale=1; viewport-fit=cover">

  1. Add the mobile-web-app-capable and status-bar-style metatags:
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">

<!-- Bonus if you want some translucency, for e.g. try default, black or black-translucent -->
<meta name="apple-mobile-web-app-status-bar-style"
    content="black-translucent">
Related