PWA - beforeinstallprompt not called
Asked Answered
F

7

50

Hello I'm trying to install a custom PWA "Add to Homescreen".

The ServiceWorkerRegistration is successful.

But the function beforeinstallpromp is not calling after register.

<script type="text/javascript">

  function request_debug(paramdata){

    document.getElementById('output').innerHTML += '<BR>'+ paramdata;

  }

  window.addEventListener('load', function() {

      document.getElementById('output').style.display = "block"; 

      if('serviceWorker' in navigator) {

      navigator.serviceWorker.register('sw.js').then(function(registration) {
        console.log('Service worker  registrado com sucesso:', registration);
        request_debug(registration);

      }).catch(function(error) {
        console.log('Falha ao Registrar o Service Worker:', error);
        request_debug(error);

      });

          var isTooSoon = true;
          window.addEventListener('beforeinstallprompt', function(e) {

              //e.preventDefault();
              //e.prompt();
              //promptEvent = e;
              request_debug(' window.addEventListener beforeinstallprompt fired!')

              if (isTooSoon) {
                //e.preventDefault(); // Prevents prompt display
                // Prompt later instead:
                setTimeout(function() {
                  isTooSoon = false;
                  e.prompt(); // Throws if called more than once or default not prevented
                }, 4000);
              }

          });

    }else{

      console.log('serviceWorker not in navigator');
      request_debug('serviceWorker not in navigator');

    }


  });

</script>

Also my service worker in root directory... HTTPS is secure!

my manifest:

{
  "background_color": "purple",
  "description": "lojaportaldotricot TESTE",
  "display": "standalone",
  "icons": [
    {
      "src": "/componentes/serviceWorker/fox-icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "name": "lojaportaldotricot",
  "short_name": "lojaportaldotricot",
  "start_url": "/dashboard"
}

It's only workes when I set "Enable" chrome://flags/#bypass-app-banner-engagement-checks


Edit: Look's like I've found the problem. The Audits tabs of Chrome's DevTools(F12) gives debugging information. enter image description here

Fecula answered 8/6, 2018 at 14:15 Comment(3)
How did you get this debugging information ?Amesace
On chrome using debug with F12Fecula
In Chrome, you may also need to install the Lighthouse extension from Google to get this menu to show up.Coldshoulder
P
43

Try this :

<script>
    let deferredPrompt;

    window.addEventListener('beforeinstallprompt', function(event) {
        // Prevent Chrome 67 and earlier from automatically showing the prompt
        e.preventDefault();
        // Stash the event so it can be triggered later.
        deferredPrompt = e;
    });

    // Installation must be done by a user gesture! Here, the button click
    btnAdd.addEventListener('click', (e) => {
        // hide our user interface that shows our A2HS button
        btnAdd.style.display = 'none';
        // Show the prompt
        deferredPrompt.prompt();
        // Wait for the user to respond to the prompt
        deferredPrompt.userChoice
        .then((choiceResult) => {
            if (choiceResult.outcome === 'accepted') {
            console.log('User accepted the A2HS prompt');
            } else {
            console.log('User dismissed the A2HS prompt');
            }
            deferredPrompt = null;
        });
    });
</script>

beforeinstallprompt will only be fired when some conditions are true :

  • The PWA must not already be installed
  • Meets a user engagement heuristic (previously, the user had to interact with the domain for at least 30 seconds, this is not a requirement anymore).
  • Your web app must include a VALID web app manifest.
  • Your web app must be served over a secure HTTPS connection.
  • Has registered a service worker with a fetch event handler.
Plafker answered 9/7, 2018 at 14:33 Comment(9)
Where to add this script code to ensure that you don't miss the beforeinstallprompt event?Sporty
@MathiasS I have had it in my index.html as well as an initialize app method in my Ionic PWA. You just want some place that gets called on the app load.Basswood
When I open it in Safari, Id does not work(with google chrome everything is great), I mean beforeinstallprompt event does not fire. Why?Quadriga
That's a very informative answer, even if it does not solve the problem, it helps with learning good things. ThanksInterdental
@MathiasS : for example, in a Vue.js app you should add it in a mounted event. The ideal place the is the layout vue filesDariusdarjeeling
This problem occurs if you put the manifest.json file on the page more than once.Marking
What is your source that 30 seconds of interaction are no longe required? And, if that is so, then what are the user engagement heuristics to be satisified? In 2021 the Google documentation specifies that 30 seconds is still required: developers.google.com/web/fundamentals/app-install-banners/…Indigence
What is btnAdd referring to? where is defined?Rechaba
service worker with fetch event handler is not required either....Hydrostatics
I
24

Along with all of those steps above, also check that the app is uninstalled here: chrome://apps

Just deleting the app from the Chrome Apps folder on your Mac does not seem to remove it from Chrome

If the app was previously installed, the beforeinstallprompt will not be triggered, and no errors will be thrown either :(

Isis answered 25/7, 2019 at 23:24 Comment(4)
This was the problem in my case... how do I get rid of this for a subsequent call? Let's say I have already installed the app, how do I reinstall it?Casar
I don't think you need to reinstall it because it is supposed to be reloaded when there is an update when service-worker kicks inJactitation
to uninstall app go to chrome://appsSpiroid
Is there a simliar way in Chrome on Android?Shields
P
7

To whoever needs to read this: A little side-note that I ran into when working on my Vue3 app while trying to figure out the prompt:

The beforeInstallPrompt will trigger shortly after the page load.

So make sure you set up the event listener close to the page load. Took me a couple of hours to find this out. I was trying to add the event listener somewhere down the line of onboarding the user. Way after the page load. And couldn't figure out why the prompt didn't show.

Puerperium answered 26/7, 2021 at 6:6 Comment(0)
S
5

Yes, the "start_url" is incorrect in the manifest.

IF ANY PART OF THE MANIFEST IS BROKEN 'beforeinstallprompt' is not fired.

The event is not fired because... the manifest start_url is incorrect.

My favorite way to figure this out is to look in the > NETWORK tab of DevTools for 404's.

AND the other way to see why manifest is broken is to run > AUDIT in DevTools and see what the error is. Like what @sealabr found:

"Failures: Service worker does not successfully serve the manifest's start_url, Timed out waiting for fetched start_url.' Which means the 'start_url"

This thread was a big help troubleshooting production. Thanks.

Stipend answered 31/12, 2018 at 21:25 Comment(0)
D
3

Are you including the manifest file in the page header?

<link rel="manifest" href="/manifest.json">
Deiform answered 11/6, 2018 at 15:2 Comment(3)
yes!! but solvet it! On Chrome, if you already have added the site to home screen, beforeinstallprompt is not going to fire. Make sure your site isn't already added to home screen, and clear Chrome's site data, and try again (ideally on a different Android phone as well).Fecula
True! You have to clear the whole Chrome cache, not only the website data of a specific domain!Ohalloran
In android how to delete the app? I have tried chrome://apps but shows nothingSacchariferous
A
1

here is another reason why beforeinstallprompt is not triggered on a mobile device (observed on an Android device with Chrome):

A symbol file defined in manifest.webmanifest could not be found on the web server (the mobile browser reported a 404). That was the reason why beforeinstallprompt was not triggered in my case.

@example

 
 // your manifest
 {
    /* ... */
    "icons": [
        {
          "src": "maskable_icon_x192.png",
          "sizes": "192x192",
          "type": "image/png",
          "purpose": "any maskable"
        },
        /*...*/
     ]
}

Make sure that all icon files (such as maskable_icon_x192.png) are present on your web server.

All the best, Tom

Awash answered 10/1, 2022 at 15:41 Comment(0)
S
1

Take note that beforeInstallPrompt event will only trigger once every page load. If you attach your event listener too late, you will never get the promptEvent.

So, you have to add the listener preferrably at your app's entrypoint (main.jsx or index.jsx), and store the promptEvent object somewhere to be used later, such as keeping it inside a your state store or some global variable.

Simulate answered 15/6 at 11:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.