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

删除回忆录丶 提交于 2019-12-31 09:23:48

问题


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.


回答1:


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




回答2:


HTML

<!-- start with hidden button -->
<button id="install" style="display:none;">install</button>

JAVASCRIPT

// variable store event
window.deferredPrompt = {};

// get button with id
const install_button = document.querySelector('#install');

// if the app can be installed emit beforeinstallprompt
window.addEventListener('beforeinstallprompt', e => {
  // this event does not fire if the application is already installed
  // then your button still hidden ;)

  // show button with display:block;
  install_button.style.display = 'block';

  // prevent default event
  e.preventDefault();

  // store install avaliable event
  window.deferredPrompt = e;

  // wait for click install button by user
  install_button.addEventListener('click', e => {
    window.deferredPrompt.prompt();
    window.deferredPrompt.userChoice.then(choiceResult => {
      if (choiceResult.outcome === 'accepted') {
        // user accept the prompt

        // lets hidden button
        install_button.style.display = 'none';
      } else {
        console.log('User dismissed the prompt');
      }
      window.deferredPrompt = null;
    });
  });
});

// if are standalone android OR safari
if (window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true) {
  // hidden the button
  install_button.style.display = 'none';
}

// do action when finished install
window.addEventListener('appinstalled', e => {
  console.log("success app install!");
});



回答3:


I don't see how this is the correct answer, because this is basically a check if user uses the App already, but the behavior we wan't is "When the user is on the web and tries to install the app again to tell him that he already has the app in his device". Upon me this is not an answer that solves this.

What we can do is: 1. When the user clicks install but has the application on his device In this case the beforeinstallprompt event WON'T BE fired so this event will return null. We store the result in global variable and when the result is null we show this to user that he already has the app installed. 2. When the user clicks install but doesn't have the application on his device In this case the beforeinstallprompt event WILL be fired so this event will return access to show the prompt. We can store the result in global variable and if it is not NULL (which won't be) because beforeinstallprompt will be fired if the user don't have the app on his device we show the prompt() to the user.

I doubt if mine solution is good too but I think that the Question and the correct answer don't have nothing in common

window.addEventListener("beforeinstallprompt", event => {
  window.deferedPrompt = event;
});

handleButtonClick = () => {
 const promptEvent = window.deferedPrompt;
 if(!promptEvent){
 // DO SOMETHING
 }
//Show the add to home screen prompt
promptEvent.prompt()

promptEvent.userChoice.then((result: any) => {
      // Reset the deferred prompt variable, since
      // prompt() can only be called once.
      window.deferedPrompt = null;.
    });
}



<button onClick={handleButtonClick}>Install</button>


来源:https://stackoverflow.com/questions/51735869/check-if-user-has-already-installed-pwa-to-homescreen-on-chrome

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!