重试地理位置请求而不刷新浏览器

时间:2016-11-02 13:56:01

标签: javascript geolocation

我对Geolocation api有一个具体问题。这是我的情景:

  1. 用户登陆页面(在Chrome - Android中),GPS位置已停用。
  2. 页面上有一个按钮,按下按钮会触发5 * 4 * 3 * 2 * 1 * 1
  3. 地理位置转到错误回调,错误消息“用户拒绝地理定位”
  4. 用户转到Android设置(主要在通知抽屉中)并启用位置
  5. 用户再次点击该按钮(此时,位置可用)以获取坐标
  6. 但是,Geolocation api仍然会抛出错误“User denied Geolocation”
  7. -

    1. 此时,地理定位请求仅在用户刷新页面并按下按钮时才会起作用(注意:该位置仍处于启用状态)
    2. 有没有办法在没有浏览器刷新的情况下完成这项工作?

      以下是jsbin链接:https://output.jsbin.com/pihenud

1 个答案:

答案 0 :(得分:2)

最后,我能够使用iFrame hack来解决这个问题。

以下是解决方案:

不是在主窗口中询问权限,而是动态创建iFrame并调用其中的geolocation.getCurrentPosition。现在,我们可以使用window.postMessage将位置数据传递到父浏览器窗口。

当我们必须再次重试地理位置请求时,我们只需要重新加载iframe - 这将有新的网站设置。

以下是iframe代码,如果有人想尝试:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Namshi Geolocation</title>
</head>
<body>
  <script type="text/javascript">
    var sendMessage = function(result){
      window.postMessage(JSON.stringify(result), window.location.origin);
    };

    var triggerGeolocationRequest = function(){
      var options = {
        enableHighAccuracy: true,
        timeout: 10000,
        maximumAge: 0
      };

      var result;

      if(window.navigator.geolocation){
        window.navigator.geolocation.getCurrentPosition(function(position){
          var result = {
            type: 'success',
            data: {lat: position.coords.latitude, lng: position.coords.longitude}
          };
          sendMessage(result);
        }, function(err){
          var result = {
            type: 'error',
            data: { message: err.message, code: err.code }
          };
          sendMessage(result);
        }, options)
      } else {
        result = {
          type: 'error',
          data: { message: 'No Geolocation API' }
        };
        sendMessage(result);
      }
    };
    window.addEventListener('load', triggerGeolocationRequest);
  </script>
</body>
</html>

在您的应用程序代码中,您可以使用实用程序来注入iFrame。请参阅以下代码:

utils.getCurrentPosition = function(){
  return new Promise(function(resolve, reject){
    var ifr = document.createElement('iframe');
    ifr.style.opacity = '0';
    ifr.style.pointerEvents = 'none';
    ifr.src = location.origin + '/geo.html'; // the previous html code.

    document.body.appendChild(ifr);

    ifr.contentWindow.addEventListener('message', function(message){
      message = JSON.parse(message.data);
      if(message.type === 'success'){
        resolve(message.data);
      } else {
        reject(message.data);
      }
      document.body.removeChild(ifr);
    });
  });
};