Android LBS系列05 位置策略(一)

Location Strategies

 

定位的实现

  在Android系统上实现定位主要是通过GPS或者是基于网络的定位方法。

  GPS是精度最高的,但是它只在户外有用,并且很耗电,并且首次定位花费时间较长。

  基于网络的定位利用通信网络蜂窝基站和Wi-Fi信号,这种定位方式在室内室外都能用,响应时间较短,耗电较少,但是精度较差。

  为了在应用中获得用户的信息,你的location provider可以是GPS或者基于网络,也可以两者都用。

 

决定用户位置面临的挑战

  从手机上获取用户的位置是个比较复杂的问题,无论采取的数据源是什么,总是有一些因素会导致位置信息包含误差,从而不准确。

  误差来源如下:

  多种位置信息源

  GPS, Cell-ID, 和Wi-Fi都能为用户位置提供一定的线索。决定信任和采用哪些数据是一个需要权衡的过程,权衡时要考虑精度、速度、电池效率等。

  用户移动

  因为用户的位置会改变,所以应该考虑每隔一段时间重新估计用户位置。

  变化的精度

  每一个位置信息源的精度不是恒定的。也就是说位置估计即便是同一个信息源提供的,它的精确度也是不断在变化的。

 

请求位置更新

  在Android中获取位置主要是通过回调函数。

  首先通过 LocationManager的 requestLocationUpdates()方法注册监听器,向其中传入一个实现了 LocationListener接口的对象。

  你的 LocationListener对象中必须实现一些回调函数,当用户位置改变或者当服务状态改变时,Location Manager就会调用这些回调函数。

  比如,下面的代码就展示了如何定义一个 LocationListener然后请求位置更新:

 

// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() 
{public void onLocationChanged(Location location) {// Called when a new location is found by the network location provider.
      makeUseOfNewLocation(location);}public void onStatusChanged(String provider, int status, Bundle extras) {}public void onProviderEnabled(String provider) {}public void onProviderDisabled(String provider) {}};// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

 

   requestLocationUpdates() 中的第一个参数指明了location provider的类型,第二个参数是通知的最小时间间隔,第三个参数是通知的最小的改变距离。

  如果第二个和第三个参数都设置成0就表示要尽可能频繁地请求位置通知。

  最后一个参数是用户自己定义的实现了LocationListener接口的对象,它接收位置更新的回调。

  如果想要同时利用GPS和网络定位,可以调用 requestLocationUpdates()两次,第一个参数分别是 GPS_PROVIDER和 NETWORK_PROVIDER 。

 

权限设置

  如果没有权限设置,程序在请求位置更新时将会失败。

<manifest ... ><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />...
</manifest>
 

  如果用NETWROK_PROVIDER, 那么需要声明 ACCESS_COARSE_LOCATIONINTERNET

  如果用GPS_PROVIDER, 那么需要声明 ACCESS_FINE_LOCATION

  ACCESS_FINE_LOCATION是包含了ACCESS_COARSE_LOCATION的,所以两者都用时可以只声明ACCESS_FINE_LOCATION

 

建立一个最佳性能的模型

  为了克服获取用户位置时的种种困难,定义一个模型,具体化你的应用如何取得用户位置。

  这个模型包含了你何时开始和何时终止位置更新的监听,也包含了什么时候使用缓存的位置数据。

获取用户位置的流程

  获取用户位置的典型流程如下:

                         

 

    1.首先开始应用。

    2.在某一个点,开始监听位置更新。

    3.维持一个当前位置的“最佳估计”。

    4.停止对位置更新的监听。

    5.利用最后一次的最佳位置估计。

  这个模型是一个窗口,窗口从开始监听开始,从停止监听结束。

 

决定何时开始监听更新

  可以从应用一开始就启动监听,也可以在用户触发某个特性后开始。

  要清楚如果长时间监听位置会消耗很多电量,但是短时间的监听可能达不到足够的精度。

  调用requestLocationUpdates()开始监听:

LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
// Or, use GPS location data:
// LocationProvider locationProvider = LocationManager.GPS_PROVIDER;

locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);

 

用上次定位的结果获取快速定位

  初次获得位置信息可能会花费较长时间。在获得一个比较精确的定位之前,可以利用一个缓存的位置:调用getLastKnownLocation(String)方法实现。

LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
// Or use LocationManager.GPS_PROVIDER

Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
 

决定何时停止监听

  位置获取和位置使用之间的时间间隔越小,对估计精度的改善越有利。

  永远记住长时间的监听位置更新将会非常费电,所以一旦你得到你需要的信息,就应该停止监听位置更新,调用removeUpdates(PendingIntent)方法实现:

// Remove the listener you previously added
locationManager.removeUpdates(locationListener);
 

维护一个当前最佳估计

  因为定位精度是实时变化的,所以很可能最新的位置并不是最准确的。

  你应该制定一些标准并包含一套逻辑判断,来选择出最佳估计。

  这套标准也是随着使用情景而变化的。

  下面是你验证一个location fix的精确度时可以采取的步骤:

    1.检查是否当期位置数据比之前的估计数据要新很多;

    2.检查当前数据和之前数据的精度,谁更好;

    3.检查当前数据是从哪个provider处获得的,然后决定是否更加信任它;

  一个例子如下:

 
选择最佳位置估计的一个例子
private static final int TWO_MINUTES = 1000 * 60 * 2;/** Determines whether one Location reading is better than the current Location fix* @param location  The new Location that you want to evaluate* @param currentBestLocation  The current Location fix, to which you want to compare the new one*/
protected boolean isBetterLocation(Location location, Location currentBestLocation) 
{if (currentBestLocation == null) {// A new location is always better than no locationreturn true;}// Check whether the new location fix is newer or olderlong timeDelta = location.getTime() - currentBestLocation.getTime();boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;boolean isNewer = timeDelta > 0;// If it's been more than two minutes since the current location, use the new location// because the user has likely movedif (isSignificantlyNewer) {return true;// If the new location is more than two minutes older, it must be worse
    } else if (isSignificantlyOlder) {return false;}// Check whether the new location fix is more or less accurateint accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());boolean isLessAccurate = accuracyDelta > 0;boolean isMoreAccurate = accuracyDelta < 0;boolean isSignificantlyLessAccurate = accuracyDelta > 200;// Check if the old and new location are from the same providerboolean isFromSameProvider = isSameProvider(location.getProvider(),currentBestLocation.getProvider());// Determine location quality using a combination of timeliness and accuracyif (isMoreAccurate) {return true;} else if (isNewer && !isLessAccurate) {return true;} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {return true;}return false;
}/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) 
{if (provider1 == null) {return provider2 == null;}return provider1.equals(provider2);
}
 

调整模型以节约电量和进行数据交换

  当你测试模型的时候,可能发现你的模型需要做一些调整,以平衡它的准确度和性能。下面是一些你可以改变的地方:

  减小流程的窗口尺寸

  窗口尺寸减小,意味着与GPS和网络的交互减少,这样就可以节约电量。但是这样也就减少了获得最佳位置估计可以利用的位置数。

  降低location provider返回更新的频率

  在窗口中降低更新频率也可以改善电池效率,但是会导致精度的丢失。requestLocationUpdates() 通过其中两个参数就可以设定更新的时间和空间间隔,从而设定频率。

  限制provider

  根据应用的特定环境或者目标精度等级,可以选择只利用基于网络的定位或者只利用GPS定位,而不是同时利用两者。只与其中的一者交互将减少电量使用,但是会有潜在的精度丢失。

 

参考资料:

  API Guides:Location Strategies

  http://developer.android.com/guide/topics/location/strategies.html

 

 

转载于:https://www.cnblogs.com/mengdd/archive/2013/01/12/2857859.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400930.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ABP官方文档翻译 3.1 实体

实体 实体类聚合根类 领域事件常规接口 审计软删除激活/失活实体实体改变事件IEntity接口实体是DDD(领域驱动设计)的核心概念之一。Eric Evans描述它为"An object that is not fundamentally defined by its attributes, but rather by a thread of continuity and identi…

目标检测之线段检测---lsd line segment detector

&#xff08;1&#xff09;线段检测应用背景 &#xff08;2&#xff09;线段检测原理简介 &#xff08;3&#xff09;线段检测实例 a line segment detector &#xff08;4&#xff09;hough 变换和 lsd 的区别 ---------------------author&#xff1a;pkf ------------------…

利用Mac创建一个 IPv6 WIFI 热点

标签&#xff1a; iOSIPv6Create NAT64 NetWork创建NAT64网络2016-05-20 10:58 14156人阅读 评论(11) 收藏 举报分类&#xff1a;开发技巧&#xff08;8&#xff09; 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 苹果商店6月1日起&#xff0c;强…

经典电影

那些经典的电影&#xff0c;第一波&#xff01;&#xff01; 《怦然心动》&#xff0c;欧美电影——布莱斯全家搬到小镇&#xff0c;邻家女孩朱丽前来帮忙。她对他一见钟情&#xff0c;心愿是获得他的吻。两人是同班同学&#xff0c;她一直想方设法接近他&#xff0c;但是他避之…

go-zero 微服务实战系列(一、开篇)

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

大数据时代,怎么做全渠道的营销

大数据时代,怎么做全渠道的营销 营销在中国有很多变化&#xff0c;1978年之前主要是计划经济的时代&#xff0c;寻求政府的保护。1984年进入商品经济之后&#xff0c;中国企业通过大规模的扩大生产&#xff0c;扩大工厂得到生产效率。1992年进入市场经济之后&#xff0c;会涌现…

oracle slient静默安装并配置数据库及仅安装数据库不配置数据库shell

oracle slient静默安装并配置数据库及仅安装数据库不配置数据库shell <1&#xff0c;>仅安装数据库软件不配置数据库 ./x86oracle.sh /ruiy/ocr/DBSoftware/app/oracle /ruiy/ocr/DBSoftware/app/oraInventory /ruiy/ins_soft.rsp <2&#xff0c;>静默安装数据库软…

hdu 2048 神、上帝以及老天爷

题解&#xff1a; 本题主要思路是&#xff0c;算出i个人的总选择数a和以悲剧结尾的总选择数b&#xff0c;然后b/a&#xff0c;完成。属于递推题&#xff1a; 图中横杠代表人&#xff0c;竖杠代表签名。Ai代表i个人共有A[i]个选择&#xff0c;Bi起过度作用。因为最多有20人&…

探究Presto SQL引擎(3)-代码生成

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

【学习笔记】计算几何

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

支持自动水平拆分的高性能分布式数据库TDSQL

随着互联网应用的广泛普及&#xff0c;海量数据的存储和访问成为系统设计的瓶颈问题。对于大型的互联网应用&#xff0c;每天几十亿的PV无疑对数据库造成了相当高的负载。给系统的稳定性和扩展性造成了极大的问题。通过数据的切分来提高系统整体性能&#xff0c;扩充系统整体容…

一些有趣的B+树优化实验

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

Tarjan的强联通分量

求强联通分量有很多种。 《C信息学奥赛一本通》 中讲过一个dfs求强联通分量的算法Kosdaraju&#xff0c;为了骗字数我就待会简单的说说。然而我们这篇文章的主体是Tarjan&#xff0c;所以我肯定说完之后再赞扬一下Tarjan大法好是不是 首先我们讲一下强联通分量 强联通分量指的…

XXE漏洞

简介 XXE (XML External Entity Injection) 漏洞发生在应用程序解析 XML 输入时&#xff0c;没有禁止外部实体的加载。 简单的理解&#xff0c;一个实体就是一个变量&#xff0c;可以在文档中的其他位置引用该变量。 实体主要分为四种&#xff1a; 内置实体 (Built-in entities…

Linq之Expression高级篇(常用表达式类型)

目录 写在前面 系列文章 变量表达式 常量表达式 条件表达式 赋值表达式 二元运算符表达式 一元运算符表达式 循环表达式 块表达式 总结 写在前面 首先回顾一下上篇文章的内容&#xff0c;上篇文章介绍了表达式树的解析和编译。如果忘记了&#xff0c;可以通过下面系列文章提供的…

NetCore框架WTM的分表分库实现

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

WordPress WP Photo Album Plus插件‘wppa-tag’跨站脚本漏洞

漏洞名称&#xff1a;WordPress WP Photo Album Plus插件‘wppa-tag’跨站脚本漏洞CNNVD编号&#xff1a;CNNVD-201301-458发布时间&#xff1a;2013-01-24更新时间&#xff1a;2013-01-24危害等级&#xff1a; 漏洞类型&#xff1a;跨站脚本威胁类型&#xff1a;远程CVE编号&…

SpringCloudAlibaba分布式流量控制组件Sentinel实战与源码分析(上)

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

【单元测试框架unittest】

转载于:https://www.cnblogs.com/ppppying/p/6899750.html

C++ 炼气期之基本结构语法中的底层逻辑

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…