Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

check if user has already installed PWA to homescreen on Chrome?

I'm trying to create an "Add To Home Screen" button on my progressive web app, as described in Chrome's documentation.

I'm generally following the prescribed pattern, where I have some hidden button which is displayed when Chrome's beforeinstallprompt event fires. I capture the event once it fires, and then use the event to begin the native install dialogue once my own install button is clicked. The sample code is below:

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;   // Update UI notify the user they can add to home screen   btnAdd.style.display = 'block'; });  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;     }); }); 

The issue I'm running into is that I don't want to show my install button (btnAdd) if the user has already installed the web app to thier home screen, and I'm having trouble figuring out how to check for that scenario.

I was hoping to modify the above code as follows:

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;    // If the user has not already installed...   deferredPrompt.userChoice     .then(choiceResult => {       if (choiceResult === undefined) {         // Update UI notify the user they can add to home screen         btnAdd.style.display = 'block';       }     }); }); 

So that the install button won't be displayed if the user has already installed. But this doesn't seem to work. It appears that if they haven't made a choice already, accessing userChoice just prompts the user directly with the native dialogue.

I'm not really sure how the beforeinstallevent works, so this might not even be a good strategy. Ideally I was hoping this would work something like something like navigator.serviceWorker.ready(), which returns a Promise rather than using browser events to try and figure out when stuff is ready.

In any case, are there any ideas on how I can check that the user has installed to home screen before I show my own home screen install button?

Edit: As Mathias has commented, checking for the event before showing the button should be sufficient. I believe the issue I was having is a result of using localhost, which appears to continually fire the beforeinstallprompt event even after installation, which is not the intended behavior. Hosting the code solved the issue.

like image 239
David Scales Avatar asked Aug 07 '18 21:08

David Scales


People also ask

How do you know if a PWA is already installed?

Check if your PWA is installed #getInstalledRelatedApps() from within the scope of your PWA to check if it is installed.

How do I track PWA installed?

First, you can use the getInstalledRelatedApps() API to check if your PWA is already installed. You can check what 'state' the PWA is running in (browser tab, or standalone window) with a little JavaScript to check to see if the CSS display mode is standalone .

How do you show PWA install banner add to your home screen?

Open the menu next to the URL bar. Depending on whether you're using Chrome or Android you'll see a menu option "Install" or "Install App". This is the "Add to Home screen" option displayed for any site that has the necessary features in place.


2 Answers

Perhaps, don't show the button until you intercept the automatic pop-up?

or
In your code, check to see if the window is standalone
If it is, you need not show the button

if (window.matchMedia('(display-mode: standalone)').matches) {       // do things here       // set a variable to be used when calling something       // e.g. call Google Analytics to track standalone use    }   

My example tester here
https://a2hs.glitch.me

Source code for my tester
https://github.com/ng-chicago/AddToHomeScreen

like image 193
Mathias Avatar answered Sep 23 '22 12:09

Mathias


To answer original question. With latest versions of Chrome you can use window.navigator.getInstalledRelatedApps(). It returns a promise with an array of installed apps that your web app specifies as related in the manifest.json. To enable this to work you need to add related_applications field to manifest.json

  "related_applications": [{     "platform": "webapp",     "url": "https://app.example.com/manifest.json"   }] 

And then you can use it like:

//check if browser version supports the api if ('getInstalledRelatedApps' in window.navigator) {   const relatedApps = await navigator.getInstalledRelatedApps();   relatedApps.forEach((app) => {     //if your PWA exists in the array it is installed     console.log(app.platform, app.url);   }); } 

Source: API docs

Now you can display some elements depending if your app is installed. E.g: you can display "Open app" button and redirect user to PWA. But remember to disable it when the user is already in the app using @Mathias's answer and checking (display-mode: standalone)

However, regarding your use case. You should display install button only when beforeinstallprompt is intercepted. Browser does not fire this event if the PWA is already installed on the device. And when prompt is fired and choiceResult.outcome === 'accepted' you hide the button again.

like image 36
DLesjak Avatar answered Sep 23 '22 12:09

DLesjak