简单的工作室

android手机定位

时间:2014-10-25 08:53来源:http://www.cnblogs.com/peer/ar 作者:简单的工作室 点击:
做移动互联网就不太可能不碰手机端的开发。上周为了项目需要,俺也挽袖子抡胳膊开始写起了android程序,还好有java基础,倒也上手快,写了几个小程序,主要都是关于定位方面的。 网上也搜得到一些相关的文章和教程,但给出的例子效果不太好,而且感觉只有其表,却不明其

做移动互联网就不太可能不碰手机端的开发。上周为了项目需要,俺也挽袖子抡胳膊开始写起了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上要想获取定位信息,

必须使用异步方式。

代码大概是这个样子:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
locManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); 
locListener = new LocationListener() { 
    @Override 
    public void onStatusChanged(String provider, int status, 
            Bundle extras) { 
        // TODO Auto-generated method stub 
    
    @Override 
    public void onProviderEnabled(String provider) { 
        // TODO Auto-generated method stub 
    
    @Override 
    public void onProviderDisabled(String provider) { 
        // TODO Auto-generated method stub 
    
    @Override 
    public void onLocationChanged(Location location) { 
        // TODO Auto-generated method stub 
        mobileLocation = location; 
    
}; 
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平台最后一次获取到的位置信息。比如,你可以这样:

  1. 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信息是否可以被接受。

(责任编辑:简单的工作室)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片