问题描述

  1. cordova页面中使用高德地图js api AMap.Geolocation的geolocation.getCurrentPosition()方法进行定位
  2. 用手机4g打开该页面,定位失败,返回错误信息:Get ipLocation failed.
  3. 手机连接wifi后,正常定位

分析

关于高德地图的定位逻辑,可以参考:

android 获取定位信息有的手机不行 手机获取位置信息失败_服务端

官方链接:Geolocation的定位流程以及定位失败的原因?

可以看到,其顺序是:

sdk辅助定位

浏览器原生定位接口

精确ip定位

这三种方式非常重要,后面我们的解决方案是基于此的

 

在wifi情况下,其定位通过抓包可以看到其使用的是ip定位,其实是比较慢的,而且既然其使用了ip定位,那么说明其前面两种方式没有成功。

android 获取定位信息有的手机不行 手机获取位置信息失败_服务端_02

对于sdk辅助定位,可以参考官方文档:新版辅助H5页面定位

这个是要求服务端和js使用端都要做相关配置的,这个在我们直接使用的情况下(服务端没有配置)是不生效的

那么问题来了,为什么浏览器原生定位接口失败了呢?

浏览器H5是可以通过navigator.location.getCurrentLocation来获取当前位置的,但是我们在我们的工程中直接使用此方法,发现如果加了超时时间,其会报错:message: Timeout expired。如果没有加超时时间,其会报错:Geolocation has been disabled in this document by Feature Policy.

尝试着就这两个错误(主要是后面这个错误)进行解决,无果。

于是邀请了android同事来查看问题,android同事果然专业,上来就提议一起看cordova的源码,debug进去。一进去果然发现了问题:

navigator.location.getCurrentLocation其会调用cordova-plugin-geolocation的geolocation.js中的getCurrentLocation方法,但是其src中的execute方法仅仅是处理了permission相关的东西,并没有进行任何实质意义上的定位。这个就很奇怪了。代码贴出来看一下

android 获取定位信息有的手机不行 手机获取位置信息失败_服务端_03

geolocation.js

android 获取定位信息有的手机不行 手机获取位置信息失败_服务端_04

看起来似乎是个死循环的调用,看不懂了

总之,就我们目前的技术水平,觉得浏览器原生定位接口这条路走不通了,不知道这是不是cordova某个版本下的一个问题

当然高德地图官方也说明了浏览器定位失败是有很多原因的

android 获取定位信息有的手机不行 手机获取位置信息失败_高德地图_05

第一个问题没有解决,来看第二个问题:

wifi情况下通过精确ip定位定位成功,这还比较不错

但4g下,至少我们几个人的手机都是精确ip定位失败,100%的失败率,报错:Get ipLocation failed

高德官方的说法:

android 获取定位信息有的手机不行 手机获取位置信息失败_android_06

难道第二个问题也不解决了,任其如此了?

这个时候android的同事把目光投到了我们前面说的sdk辅助定位上。那问题三又来了,这个服务端哪里来呢?既然官方的cordova-plugin-geolocation不好用,那么有没有第三方的plugin呢?来到github,果然被发现了

https://github.com/ergoli/cordova-amap-location

直接src进去看了一下,完美的代码

android 获取定位信息有的手机不行 手机获取位置信息失败_服务端_07

这样就按照其介绍的方式,在高德开发者申请了android的key,生成sha1值。配好后果然可用,而且定位速度很快。

结论

1. 我的这位android同事厉害

2. 官方文档真的是要认真读,认真思考