获取当前位置的坑

被一个问题不间断折磨了一周,今天终于有了眉目。

问题描述:一个工单系统,该系统可以支持网络协议切换,http,或者https的都行。然后利用工单链接,在移动端进行工单的处理。

问题:定位
在这里插入图片描述
比较坑的是:这个位置定位

 // 获取当前经纬度,是否支持定位功能?
    async getCurrentLocation() {
    
    
      if (navigator.geolocation) {
    
    
        await navigator.geolocation.getCurrentPosition(position => {
    
    
          let {
    
    longitude, latitude } = position.coords;
          this.lng = longitude;
          this.lat = latitude;
          this.switchLnglatRegion();
        }, err => {
    
    
          console.log('定位发生错误', err);
        }, {
    
    
          enableHighAccuracy: true,
          timeout: 8000,  //如果在8秒钟之内还没有得到用户信息,报出错误超时的错误
          maximumAge: 3000 // 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。
        }
        );
      } else {
    
    
        this.toast = this.$createToast({
    
    
          // Fixme: 交互没有该情况下交互文本
          txt: '当前浏览器不支持自动定位功能',
          type: 'warn',
          time: 2000
        });
        this.toast.show();
      }
    },

http协议下:
在这里插入图片描述

原因:

首先想到的是排查机型问题。由于客户多为IOS用户,所以最先看的是在安卓是有没有此问题的发生,调查结果为安卓没有任何问题。再排查IOS的版本问题,结果发现无法获取地理位置的为IOS10版本,而IOS9上同样无此现象的产生。

所以基本定位到是IOS 10版本可能对我们现在的代码没法兼容,没办法小胳膊弄不过大腿,所以我们再定位现在的代码是通过什么样的方式去获取地理位置的。

基本可以确定IOS 10可能对H5获取地理位置的API做了限制或者有了修改,具体什么修改还需要继续排查。

在网上google了一下,原来这个问题在IOS10推出就已存在,现在已经到了10.3+了我们才暴露出来,蜜汁尴尬。。

具体的原因也说的比较明白:

  在IOS 10中,苹果对webkit定位权限进行了修改,所有定位请求的页面必须是https协议的。
  如果是非https网页,在http协议下通过html5原生定位接口会返回错误,
  也就是无法正常定位到用户的具体位置,而已经支持https的网站则不会受影响。

解决方案:
基本网上有两种解决方案:

1、将网站的http设置为Https。

2、通过第三方解决,即通过调用百度地图或者腾讯地图来获取地理位置

我也想着使用第三方解决,但是我在使用百度API去获取地理位置的时候发现和真实的经纬度又有所偏差,原来百度地图对地理位置又进行了二次加密,又是一个坑,果断放弃(而且我们是国际产品,产品中已经引入了谷歌地图,在他喵引入国内地图,肯定不合适)。

而第一个方案,升级网站为https是个长期规划的过程(鬼才知道有多少个坑在里面),所以就需要找一个比较能短时间解决问题的方案。

最后终于在犄角旮旯找到了基本的解决方案:采用iframe可以绕过IOS的这一限制(但是没法绕过谷歌浏览器的限制)

var options = {
    
    
      enableHighAccuracy: true,
      maximumAge: 30000,
      timeout: 12000
    };

    window.locationCallback = function(err, position) {
    
    
      if (err) {
    
    
        window.showError(err);
        return;
      }

      window.showPosition(position);
    };
        

    var str = '<iframe src="javascript:(function(){ '
            + 'window.navigator.geolocation.getCurrentPosition('
            + 'function(position){parent && parent.locationCallback && parent.locationCallback(null,position);}, '
            + 'function(err){parent && parent.locationCallback && parent.locationCallback(err);}, '
            + '{enableHighAccuracy : ' + options.enableHighAccuracy + ', maximumAge : ' + options.maximumAge + ', timeout :' + options.timeout + '})'
            + ';})()" style="display:none;"></iframe>';
    $(str).appendTo('body');


    window.showPosition = function(position) {
    
    
      //  TODO
      console.log('position', position);
    };
    window.showError = function(error) {
    
    
      switch (error.code) {
    
    
        case error.PERMISSION_DENIED:
          alert('用户不允许地理定位!');
          break;
        case error.POSITION_UNAVAILABLE:
          alert('无法获取当前位置!');
          break;
        case error.TIMEOUT:
          alert('操作超时!');
          break;
        case error.UNKNOWN_ERROR:
          alert('未知错误!');
          break;
        default:
          break;
      }
    };

iframe解决是2017年的方案,现在是2022年,使用以上浏览器警告,好了路彻底堵死。
在这里插入图片描述
VM22653:1[弃用]getCurrentPosition()和watchPosition()不再在不安全的源上工作。
要使用此特性,您应该考虑将应用程序切换到安全源,例如HTTPS。 详见https://goo.gl/rStTGz。

解决方案:

一个思维很重要,国际产品,国际思路解决,用个锤子的百度,直接chrome搜索,最终方案:
谷歌地图官方说明链接

// 协议 post请求无入参:
https://www.googleapis.com/geolocation/v1/geolocate?key=谷歌key值
// 结果
{
    
    
    "location": {
    
    
        "lat": 35.86166,
        "lng": 104.195397
    },
    "accuracy": 1804475.2390180232
}

另一种解决方案:

function do_something(coords) {
    
    
    // Do something with the coords here
}
navigator.geolocation.getCurrentPosition(function(position) {
    
     
    do_something(position.coords);
    },
    function(failure) {
    
    
        $.getJSON('https://ipinfo.io/geo', function(response) {
    
     
        var loc = response.loc.split(',');
        var coords = {
    
    
            latitude: loc[0],
            longitude: loc[1]
        };
        do_something(coords);
        });  
    };
});

其余的解决方案就不行了,是修改浏览器设置的,很明显,不可取

猜你喜欢

转载自blog.csdn.net/weixin_43131046/article/details/124732523