参考文章:为何手机gps定位需要流量,而车载不需要?(http://blog.csdn.net/jia12216/article/details/70693373)
苹果的定位函数是成批的放回定位点的,通常一批返回3到10个不等数量的位置点信息,一般本批次最后一个点的位置和方向最准确。一批位置点通常在100毫秒内返回完全。若你想得到最准确的点,不能见点到第一个点就发送,而是延迟100毫秒收到本批次所有的点后再发送最后一个最准确的点。注意:当应用刚启动时,获取的位置一般2到3个点,这几个点的间隔可能大于100毫秒。
相信做APP的大都要用到高德地图和百度地图,并且用到获取用户位置的功能。那么你会发现,你对地图接口设置了过滤精度,结果你获取的位置很不准确,经常你在路上跑,结果在你的应用上看到你的车在河里游,让人泪流满面。来我告诉为何这样坑你你怎么获取用户的准确位置。
首先IPHONE的GPS定位在全球都能获得位置信息,不像安卓那么苦逼进了房间就定位不到位置了。原因是IPHONE手机的位置信息都是苹果定位模块返回给你的,苹果应用研发者关注IPHONE手机的定位类型(gps定位,wifi定位,基站定位),苹果都给你自动处理了,你只要关注获取的位置信息的精度就可以了。安卓手机要根据具体情况(gps定位,wifi定位,基站定位)自己处理。并且安卓获取的位置有很少的时候有以前的点蹦出来。所以安卓手机的定位很苦逼。若是你在一个山头的背面在搞得地图上定位不到你的位置,并非你的地图没有收到GPS位置信息,而是你的地图没有收录你的坐标信息。这个场景我在杭州虎跑后山的马儿上岗附近的山头测试过,在一个山头背面我写的测试应用收到GPS位置信息,但是高德地图和百度地图都没有定位信息。在上天竺山头上,我的手机从4G切换到3G网络,我写的应用收到GPS位置信息,高德地图和百度地图都没有定位信息,百度地图能加载地图完毕,高德地图加载不出来。经过测试IPHONE的应用,只要开启时有网络,以后把网络关闭,那么你的手机应用仍旧能收到位置信息,所以IPHONE获取的是GPS位置信息或基站定位信息。不像安装又是基站定位,GPS定位,网络定位N多种情况。但是IOS的GPS位置信息精度仍然受到建筑物,山脉等障碍物的影响。如经过测试在我们公司的主楼6楼上,,用4G网络定位偏离到很远的位置(500米外),打开wifi,一般开启高德地图,获取的精度大约是65,在公司外面大门口(4g网络)的精度可以达到10米–20米。
iphone和安卓确实不一样,经过我们团队在各种环境(高山,大楼,房间,偏远农村,山脚下)下测试,iphone绝对能获得经纬度,只是误差大小不同而已。而安卓手机在这些环境下基本上获取不到经纬度。大致对用户而言之有两种情况:打开wifi定位(有wifi网络),关闭wifi(无可用wifi,因为手机以wifi有限,若有wifi网络,肯定wifi网络优先,不会再用4g网络)以移动网络(4g,3g,2g网络)定位。具体手机怎么定位,具体是否以基站,gps,网络等定位,一般的用户一般不太关注。若app要用获得的经纬度来在地图上画线,那么对这种定位类型判断就要考虑了,房间内的wifi定位和基站定位靠谱了,一般要扔掉,不然你的人在小区里,那么你的位置显示在1500米外并乱画线也太离谱了。若你的手机正使用gps定位画线很正常,进入gps信号没有区域(隧道等),你的定位切换为基站定位,那么你的轨迹曲线不是会大幅度震动了吗?还好可以用定位返回的精度来过滤这种偏差大的点。
若手机开启wifi,会出现手机自动连接4g基站的免费wifi,有时候4g基站的免费wifi连接上就能上网(情景一),有时候需要你点击登录才能上网(情景二)。
情景一,由于手机优先使用wifi网络,若有wifi网络就用wifi定位,不用gps定位,会造成定位精度下降的问题。
情景二,就是典型的通而不达网络(又称受限网络),手机会收到网络正常通知,但是根本不能上网并且处于select状态的socket会出现立刻返回,并且监控不到异常的现象。
所以对于定位精度达到30米或更高要求的应用(wifi定位的典型特征是速度为-1,经常出现精度值是65),一定要关闭wifi,防止手机自动连接wifi而使精度莫明奇妙的降低。
以高德地图为例:
高德有两种位置过滤位置信息的设置:设置过滤距离,设置期望精度。
_mapView.distanceFilter = 20.0;
// _mapView.desiredAccuracy = kCLLocationAccuracyHundredMeters;
当你设置了过滤精度后,实际上当你的应用启动时,有3个精度都超过20米(达到65米精度)的点进入if(updatingLocation)的下面的语句。并不是你期望的位置坐标,以后还有精度达到20米–45米的点进入里面,所以是期望吗?不靠谱。
-(void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation { if(updatingLocation) { //保存位置信息和位置相关操作,如画车子的运行轨迹 } }
言归正传,如何获得精度达到20米的点呢,当然要靠进度来判断了。注意若某片区域GPS信号不好,收不到精度达不到20米的位置信息,那么你可能过滤掉所有的位置信息,那么你的车在这个区域将没有轨迹。谁让你过滤的太狠呢!你对我太狠我人间暂时人间蒸发一段时间。因为我们的应用曹操专车,所以不考虑车子的垂直高度,只考虑水平精度,你若想控制水平精度,那么你就自己控制吧!若你对精度控制还不满意,建议再采取三点滤波法(取最近的三点,若第2个点误差太大,就干掉第二个点).
正确的获取位置代码(不考虑垂直精度的场景)是:
-(void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation { if(updatingLocation) { if(userLocation.location.horizontalAccuracy <= 20.0) { //保存位置信息和位置相关操作,如画车子的运行轨迹 } } }