11.1.4 定位实例

在实际开发中,使用定位服务有很多值得关注的地方,我们可以通过一些开源的实际项目来学习和了解一下。Foursqaure[1]是世界上最热门的基于地理信息的签到应用。它可以记录使用者所在的地方,获取所在地点周边的相关信息,并了解好友都在哪里、做了什么。对于这样一款移动应用而言,精准的定位是最重要的一项工作。

Foursquare的Android版本曾经是开源项目[2](现在已经停止源代码的开放,只能获得之前版本的源代码),在定位方面,它有一些比较好的实现方式值得学习。

Foursquare采取了动态选择位置信息的策略。它定义了一个BestLocationListener对象,实现了android.location.LocationListener接口,用来监控设备上各个信息源监控到的信息变化,综合这些信息最终计算出当前最可能的位置信息:


public class BestLocationListener extends Observable

implements LocationListener{

//存储最近一次更新过的位置信息

private Location mLastLocation;

@Override

public void onLocationChanged(Location location){

//当某个位置信息源监听到位置变化时,会调用该函数

//需要动态判断该位置信息是否足够精准,能够采用

if(mLastLocation==null){

//如果是第一次获得定位信息,则采用

onBestLocationChanged(location);

return;

}

//比较两次定位的精度,如果新的位置信息精度低于原有的,则放弃

boolean has_new_accuracy=location.hasAccuracy();

boolean has_old_accuracy=mLastLocation.hasAccuracy();

if(!has_new_accuracy&&has_old_accuracy){

//原来有精度信息,现在没有,则放弃

return;

}

if(has_new_accuracy&&has_old_accuracy&&

location.getAccuracy()<=mLastLocation.getAccuracy()){

//都有精度,但新的低于老的,则放弃

return;

}

//如果新的定位精度要优于老的,还需要考量时间

if(IsTooOld(mLastLocation)){

//如果老的定位信息太老了,则更新

onBestLocationChanged(location);

}else if(LocationBetterThenTime(location)){

//如果新的定位信息在时间阈值内足够好,则更新

onBestLocationChanged(location);

}

}

synchronized public void onBestLocationChanged(Location location){

//更新最近的位置信息,并通知监听者

mLastLocation=location;

setChanged();

notifyObservers(location);

}

synchronized public Location getLastKnownLocation(){

//读取最近的位置信息

return mLastLocation;

}

public void register(LocationManager locationManager, boolean gps){

//通过调用该函数,可以触发位置信息开始更新

}

public void unregister(LocationManager locationManager){

//通过调用该函数,可以触发位置信息停止更新

}

}


Foursquare中仅有一个BestLocationListener对象实例用来监听位置信息变化,该对象缓存在了应用环境(Application Context)对象中。Foursquare中的各个组件可以通过应用环境提供的接口,随时获取到最新的位置信息,对已有位置信息进行更新或者监听。这样的策略,使得在Foursquare中的定位信息是一致的,并且随处可以取用的,简化了开发复杂度:


//Foursquare的应用环境对象

public class Foursquared extends Application{

//构建定位监听对象,在整个应用中是个单件

private BestLocationListener mBestLocationListener=new

BestLocationListener();

//更新位置信息,并监控其变化

public BestLocationListener requestLocationUpdates(

Observer observer){

mBestLocationListener.addObserver(observer);

mBestLocationListener.register((LocationManager)getSystemService(Context.

LOCATION_SERVICE),true);

return mBestLocationListener;

}

//停止更新位置信息,不再监听其变化

public void removeLocationUpdates(Observer observer){

mBestLocationListener.deleteObserver(observer);

mBestLocationListener.unregister((LocationManager)getSystemService(Context.

LOCATION_SERVICE));

}

//读取上次定位的信息

public Location getLastKnownLocation(){

return mBestLocationListener.getLastKnownLocation();

}

}


从Foursquare的实践中可以看到,如果用户需要大量使用位置信息,构建一套适合的位置选择策略,并将最近的位置信息全局缓存起来随时使用,是非常有效的策略。

[1]Foursquare的官方网站:http://foursquare.com。

[2]Foursquare Android版本的开源服务地址在Google Code上:http://code.google.com/p/foursquared/。