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/。