android定位方式
做移动互联网就不太可能不碰手机端的开发。上周为了项目需要,俺也挽袖子抡胳膊开始写起了android程序,还好有java基础,倒也上手快,写了几个小程序,主要都是关于定位方面的。
网上也搜得到一些相关的文章和教程,但给出的例子效果不太好,而且感觉只有其表,却不明其理。因此写出此文,分享一些我的经验。虽然是以android为主,但是我想对其它平台的开发也应该有些帮助。
这篇文章侧重于制定一个合理的定位方案。
手机定位的方式
先科普一些基础知识吧。
最简单的手机定位方式当然是通过GPS模块(现在大部分的智能机应该都有了)。GPS方式准确度是最高的,但是它的缺点也非常明显:1,比较耗电;2,绝大部分用户默认不开启GPS模块;3,从GPS模块启动到获取第一次定位数据,可能需要比较长的时间;4,室内几乎无法使用。这其中,缺点2,3都是比较致命的。需要指出的是,GPS走的是卫星通信的通道,在没有网络连接的情况下也能用。
另外一种常见的定位方式是基站定位。大致思路就是采集到手机上的基站ID号(cellid)和其它的一些信息(MNC,MCC,LAC等等),然后通过网络访问一些定位服务,获取并返回对应的经纬度坐标。基站定位的精确度不如GPS,但好处是能够在室内用,只要网络通畅就行。
还有Wifi定位。和基站定位类似,这种方式是通过获取当前所用的wifi的一些信息,然后访问网络上的定位服务以获得经纬度坐标。因为它和基站定位其实都需要使用网络,所以在Android也统称为Network方式。
最后需要解释一点的是AGPS方式。很多人将它和基站定位混为一谈,但其实AGPS的本质仍然是GPS,只是它会使用基站信息对获取GPS进行辅助,然后还能对获取到的GPS结果进行修正,所以AGPS要比传统的GPS更快,准确度略高。
Android提供的定位接口
在写第一个程序之前,我对android的幻想是这样的:提供了一个函数,能够让我直接从GPS模块中读取经纬度坐标,还有一个函数,能够直接访问网络,获得基站定位的结果。所以,我只需要调用调用函数就可以搞定这一切。
现实和理想总是有很大的差距。Android上的开发完全不是这么回事儿。前面提到过,GPS模块从启动到获取数据之间时间会比较长,可能有2~3分钟时间,所以,如果真有这么一个函数,那么你的程序可能会被这个函数阻塞几分钟。我想正是基于这样的考虑,android上要想获取定位信息,必须使用异步方式。
代码大概是这个样子:
01 |
locManager = (LocationManager) this .getSystemService(Context.LOCATION_SERVICE); |
02 |
locListener = new LocationListener() { |
03 |
@Override |
04 |
public void onStatusChanged(String provider, int status, |
05 |
Bundle extras) { |
06 |
// TODO Auto-generated method stub |
07 |
} |
08 |
@Override |
09 |
public void onProviderEnabled(String provider) { |
10 |
// TODO Auto-generated method stub |
11 |
} |
12 |
@Override |
13 |
public void onProviderDisabled(String provider) { |
14 |
// TODO Auto-generated method stub |
15 |
} |
16 |
@Override |
17 |
public void onLocationChanged(Location location) { |
18 |
// TODO Auto-generated method stub |
19 |
mobileLocation = location; |
20 |
} |
21 |
}; |
22 |
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener); |
这是从网上随便摘一段。简单解释一下代码:
首先,你需要创建一个LocationManager;
然后定义出自己的LocationListener,LocationListener包涵了好几个成员函数,它们都是回调函数。最重要的一个是“onLocationChanged”,这个函数是在android获取了新的location信息之后调用的,你可以在这个函数内来实现自己想要的功能。比如,你可以定义一个内部location变量,一旦这个函数被调用,就将内部location变量设置成最新的值;
最后,调用LocationManager.requestLocastionUpdates,它其实是将定义的locationListener注册到android中。在上面的代码中,这句话是说让LocationListener监听GPS_PROVIDER的变化。GPS_PROVIDER对应于android上的GPS模块获取位置信息,还有一个NETWORK_PROVIDER表示通过network方式获取位置信息。
问题
那么接下来就有问题了,什么时候能够真正获得手机的定位经纬度呢?等着onLocationChanged被调用吧。那它什么时候会被调用?没人知道。我写过一个小程序,测试Network方式下注册过listener之后(requestLocationUpdates函数)和onLocationChanged被调用之间的时间间隔。测试的网络条件很好。反复观察了几次,大部分都可以在几十毫秒内就返回了,但也有一些时候,时间间隔长达几十秒。这意味着,你的用户需要等上几十秒才能有返回。
所以,第一个需要注意的地方是,不要一直等待你的回调函数onLocationChanged被调用。你需要设置一个timeout机制。
这又会引入第二个问题。如果timeout了,但onLocationChanged仍然没有返回,怎么办?难道只能提示用户无法定位吗?
别急,android还提供了一个函数:getlastKnowLocation。这个函数会返回android平台最后一次获取到的位置信息。比如,你可以这样:
- Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
所以,即便onLocationChanged没有被调用,我们仍然可以获取一个位置信息。当然,这里又引出了第三个问题:这个的返回值值得信赖吗?
如果用过一些LBS或者地图程序,你会发现有一个现象:在某些时候你打开地图结果被定位到的地方是你上一次使用地图程序的位置。这就是因为程序是采用getLastKnownLocation获取的位置。这个问题的解决办法是,需要定义一个标准判断获取到的Location是否可信。Android的Location这个类除了包涵有latitude,longitude,还包含有很多其他的信息,比如何时获取到的,通过哪种方式获取到的,等等。程序员完全可以基于这些信息来判断获取到的Location是否过时或者是否可信。
合理的方案
最后,说一下整体方案。Android的官方文档【1】给出了推荐的方案:
首先注册自己的LocationListener,让它同时监听GPS_PROVIDER和NETWORK_PROVIDER;
然后可以调用getLastKnownLocation获得一个Location值,这个值可以作为一个备选值;
然后在一段用户可接受的时间内,不断接收从onLocationChanged返回的位置,并同之前的值做比较,选取其中的最佳;
最后,会剩下一个筛选后的最优结果,你需要判断这个结果是否可接受。如果可以接受,返回给用户,如果不行,告诉用户无法定位。
整个过程你需要定义两个重要的函数:一个是比较两个Location信息,返回其中好的那个;另一个函数则用来判断Location信息是否可以被接受。
android定位方式的更多相关文章
- 六 APPIUM Android 定位方式
文本转自:http://www.cnblogs.com/sundalian/p/5629500.html APPIUM Android 定位方式 1.定位元素应用元素 1.1通过id定位元素 An ...
- Android定位方式和测试方法
Android常用的三种定位方式有:基于GPS定位.基于基站地位.基于wifi定位. 1.基于GPS定位: GPS定位需要GPS模块(硬件)的支持,没有GPS模块是无法进行GPS定位的. GPS定位最 ...
- 七 APPIUM Android 定位方式
1.定位元素应用元素 1.1通过id定位元素 Android里面定位的id一般为resrouce-id: 代码可以这样写: WebElement element = driver.findElem ...
- APPIUM Android 定位方式
原文地址https://www.cnblogs.com/sundalian/p/5629500.html 1.定位元素应用元素 1.1通过id定位元素 Android里面定位的id一般为resrouc ...
- Android定位测试(深坑)
问题:我们是一个海外app,市场部去马来西亚打开那边的市场,发现了一个问题,就是我们的app定位有问题,还是成都的定位,主要原因是在马来西亚使用这个app,请求中带的经纬度参数是成都的,导致服务器返回 ...
- android 定位的四种方式
[原文] 开发中对于地图及地理位置的定位是我们经常要用地,地图功能的使用使得我们应用功能更加完善,下面总结了一下网络中现有对于介绍android定位的4种方式,希望对大家有帮助: android 定 ...
- android 三种定位方式
http://www.cnblogs.com/oudi/archive/2012/03/22/2411509.html 最近在看android关于定位的方式,查了很多资料,也做了相关实验,在手机上做了 ...
- android 定位的几种方式介绍
[地理位置] android 定位的几种方式介绍 开发中对于地图及地理位置的定位是我们经常要用地,地图功能的使用使得我们应用功能更加完善,下面 www.androidkaifa.com 总结了一下网络 ...
- 技术分享 | app自动化测试(Android)--元素定位方式与隐式等待
原文链接 元素定位是 UI 自动化测试中最关键的一步,假如没有定位到元素,也就无法完成对页面的操作.那么在页面中如何定位到想要的元素,本小节讨论 Appium 元素定位方式. Appium的元素定位方 ...
随机推荐
- 【读书笔记】《未来闪影》罗伯特·J·索耶
真是一本引人入胜的书! 看了不到一半,就有一种置身其中的感觉,要是我也能看到自己二十年后的生活,哪怕只有1分43秒,该是一件多么奇妙的事情.但忧虑也随之而来,如果二十年后我没有成为现在想成为的人,现在 ...
- qt+boost::asio+tcp文件传输
客户端: void qt_boost::pbSendFileClicked(){ QString filename = ui.leFileName->text(); QByteArray ba ...
- HDU 1142 A Walk Through the Forest(dijkstra+记忆化DFS)
题意: 给你一个图,找最短路.但是有个非一般的的条件:如果a,b之间有路,且你选择要走这条路,那么必须保证a到终点的所有路都小于b到终点的一条路.问满足这样的路径条数 有多少,噶呜~~题意是搜了解题报 ...
- Linux几种关机(重启)相关命令
在linux下一些常用的关机/重启命令有shutdown.halt.reboot.及init,它们都可以达到重启系统的目的,但每个命令的内部工作过程是不同的,通过本文的介绍,希望你可以更加灵活的运用各 ...
- 数据结构《17》---- 自己主动补齐之《二》----Ternary Search Tree
一. 序言 上一篇文章中,给出了 trie 树的一个实现. 能够看到,trie 树有一个巨大的弊病,内存占用过大. 本文给出还有一种数据结构来解决上述问题---- Ternary Search Tre ...
- Ubuntu下实现双屏独立切换
在编码时,总觉得屏幕大小不够,要是能多个屏多好,可以这样 把你的显示器连接到你的电脑,然后开启一个终端 输入:xrandr 显示如下: LVDS1 connected 1366x768+1024+0 ...
- XML实例文档
from: http://www.w3school.com.cn/xpath/xpath_examples.asp XML实例文档 我们将在下面的例子中使用这个 XML 文档: "books ...
- Hadoop大数据面试--Hadoop篇
本篇大部分内容參考网上,当中性能部分參考:http://blog.cloudera.com/blog/2009/12/7-tips-for-improving-mapreduce-performanc ...
- _tcscat在Debug和Release根据问题
背景: 因此,例如,在下面的代码段,作用是得到的路径当前程序(C:\work\A.exe),然后"A.exe"拆除,组装的"C:\work\inject.dll" ...
- .Net程序猿乐Android开发---(4)注册页面布局
接下来我们介绍的登陆页面布局,在本节中,我们看一下注册页面布局,页面布局大同小异,来一起熟悉下基本控件的使用方法. 效果图: 1.加入注冊页面 右键选中layout目录,加入注冊页面.例如以下图 点击 ...