Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to intercept app install prompt in Angular PWA?

I have created a PWA using Angular guidelines. I am facing problem intercepting the app install banner. I am using this code to defer it to a later point:

let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
  // Prevent Chrome 67 and earlier from automatically showing the prompt
  e.preventDefault();
  // Stash the event so it can be triggered later.
  deferredPrompt = e;
  console.log("Intercepting the app install banner prompt");

  setTimeout(function() {
    deferredPrompt.prompt();
  }, 20000);

  // 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;
  });
});

My manifest file:

{
  "name": "TreadWill",
  "short_name": "TreadWill",
  "theme_color": "#2a3b3d",
  "background_color": "#2a3b3d",
  "display": "standalone",
  "scope": "/",
  "start_url": "/",
  "icons": [
    {
      "src": "assets/icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "assets/icons/icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "assets/icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "assets/icons/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "assets/icons/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "assets/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "assets/icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "assets/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

When I try this code in localhost, the message included in the console.log is getting logged but after 20 seconds, I am getting an error:

Uncaught (in promise) DOMException

in this line:

deferredPrompt.prompt();

When I host the code and try it on mobile, the app install banner shows up instantly instead of after 20 seconds.

I have tried putting this code in the index.html file itself, in a separate js file and calling that in the index.html file. Creating a service and including almost similar code in a .ts file. Nothing has worked. Although I am trying out js solutions out of desperation, I would prefer Angular solutions to the problem. Ideally, I would like to catch and store the 'beforeinstallprompt' event in a global variable and prompt the event at different points.

How to solve this problem?

like image 567
Arka Ghosh Avatar asked Feb 13 '19 15:02

Arka Ghosh


2 Answers

You are probably doing it properly, but according to this article:
"The mini-infobar will appear when the site meets the add to home screen criteria, regardless of whether you preventDefault() on the beforeinstallprompt event or not."
So for me also, it shows immediately.

Pete LePage (@petele) is a good person to follow on twitter for updates to A2HS.

Here is the Add To Home Screen (A2HS) tester I built. There is a link to the source code on the bottom of the page. Feel free to use anything that may be helpful. I have not updated it recently to the most current version of angular. But it should all still work fine since it's basic code.
https://a2hs.glitch.me

like image 102
Mathias Avatar answered Oct 13 '22 20:10

Mathias


The links provided in Mathias' answer helped me solve the problem. I am just adding a few points that are not explicitly mentioned in the answer but might help someone else.

  • The app install banner can only be shown on some user activity. For example - a button click. It can't be prompted via setTimeout.
  • Currently, intercepting the beforeinstallprompt and showing it later works in Chrome and Edge because Chrome and Edge fires the event automatically when the user visits the site. Firefox doesn't fire the beforeinstallprompt event and hence it doesn't work on Firefox.
like image 4
Arka Ghosh Avatar answered Oct 13 '22 22:10

Arka Ghosh