如何知道渐进式Web应用程序是在前台还是后台

时间:2018-05-11 21:24:06

标签: progressive-web-apps

有没有办法知道渐进式网络应用程序是在后台还是在前台(即,它当前是应用程序的焦点,还是#34;最小化")

过去2天搜索Google和SO只提供了有关如何在后台运行服务工作者的信息。谢谢!

2 个答案:

答案 0 :(得分:3)

我已经搜索了好几天了,上面的答案很多。可见性api确实可以正常工作,但并非一直都有效。以为我会在这里发布我们的解决方案,以补充上面的答案,我们发现这是在大多数浏览器中都能使用的最可靠的方法。

对我们来说,问题最重要的是在移动设备上。我们有一个可安装的PWA,但该问题也存在于移动浏览器中。将已安装的PWA(或在移动浏览器中打开的选项卡)推送到后台后,仅凭可见性API不足。我们的应用程序依赖于通过graphql订阅进行的实时数据更新,当应用程序/浏览器进入后台时,它不再获取此数据。例如,如果用户要在收到指示他们有新消息的推送通知后打开应用程序,则该新消息不在应用程序中,因为它实际上已处于睡眠状态,并且网络套接字已关闭。我们不想每次用户在我们的应用程序和设备上其他应用程序之间移动时都必须进行完全刷新,因此使用Service Worker中的低级检查并只是重新加载页面并不能提供一个很好的功能。体验并造成很多不必要的负载。我们需要可靠地了解应用程序何时回到前台,从而在React组件内部知道它们,以便我们可以强制从后台进入时获取相关的丢失数据。

我们最终从页面生命周期的google文档中对此进行了调整。有人确实为此创建了一个小型js库,但我们无法使其正常工作。因此,我们只是改编了示例代码,并且效果很好。

https://developers.google.com/web/updates/2018/07/page-lifecycle-api

以下代码可以轻松集成到react组件中,并可以通过useState和useEffect挂钩进行管理。

import MobileDetect from 'mobile-detect';
const md = new MobileDetect(window.navigator.userAgent);
const isMobile = md.mobile();

let standalone
if (navigator.standalone) {
  standalone = 'standalone-ios';
}
if (window.matchMedia('(display-mode: standalone)').matches) {
  standalone = 'standalone';
}

const getState = () => {
  if (document.visibilityState === 'hidden') {
    return 'hidden';
  }
  if (document.hasFocus()) {
    return 'active';
  }
  return 'passive';
};

let displayState = getState();

const onDisplayStateChange = () => {
  const nextState = getState();
  const prevState = displayState;

  if (nextState !== prevState) {
    console.log(`State changed: ${prevState} >>> ${nextState}`);
    displayState = nextState;

    //standalone will restrict to only running for an installed PWA on mobile
    if (nextState === 'active' && isMobile /* && standalone */) {  
      //The app/browser tab has just been made active and is visible to the user
      //do whatever you want in here to update dynamic content, call api etc
    }
  }
};

//subscribe to all of the events related to visibility
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
  window.addEventListener(type, onDisplayStateChange, {capture: true});
});

答案 1 :(得分:2)

从客户端,您可以使用Page Visibility API查询当前的可见性,并在可见性发生变化时获取事件。

const state = document.visibilityState;

document.addEventListener('visibilitychange', () => {
  console.log(document.visibilityState);
});

从服务工作者,您还可以使用WindowClient查询客户的可见性状态。

event.waitUntil(
  clients.matchAll({ type: 'window' })
    .then(function(clientList) {
      for (var i = 0; i < clientList.length; i++) {
        const state = clientList[i].visibilityState;
      }
    })
);