我们在开发LBS类应用时必然会用到Android的定位,本文来看看Android下的不同精度的定位,以及如何判断定位是否更精确。
首先,我们需要1个LocationManager类:
locationManager = (LocationManager)this
.getSystemService(Context.LOCATION_SERVICE);
有了locationManager之后,我们便可以开始监听位置的变化了,使用LocationManager中的方法:
来设置监听器。
第一个参数2选1,分别是:LocationManager.NETWORK_PROVIDER和LocationManager.GPS_PROVIDER,前者使用移动网络依靠基站获取位置,精度低速度快,后者使用GPS进行定位,精度高但一般需要10-60秒时间才能开始第1次定位,如果是在室内则基本上无法定位。
这2种Provider肯定是互补的,本文中,我们要同时开启2个监听,但基于移动网络的监听只会执行一次就会被停止,而基于GPS的监听则会一直持续下去。
首先,我们会声明1个监听器的内部类,这个类会同时用于2种模式的监听,还要声明1个currentLocation,用于记录当前的位置。
@Override
public void onLocationChanged(Location location) {
Log.i("LocationTest", "Got The New Location of provider:"+location.getProvider());
if(currentLocation!=null){
if(isBetterLocation(location, currentLocation)){
Log.i("LocationTest", "It’s a better location");
currentLocation=location;
showLocation(location);
}
}
else{
Log.i("LocationTest", "First location");
currentLocation=location;
showLocation(location);
}
//移除LocationManager.NETWORK_PROVIDER的监听器
if(LocationManager.NETWORK_PROVIDER.equals(location.getProvider())){
locationManager.removeUpdates(this);
}
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
};
Location currentLocation;
//测试
private void showLocation(Location location){
//纬度
Log.i("LocationTest", "Latitude:"+location.getLatitude());
//经度
Log.i("LocationTest", "Longitude:"+location.getLongitude());
//精确度
Log.i("LocationTest", "Accuracy:"+location.getAccuracy());
}
在showLocation方法中,打印了location的Accuracy属性,一般来说NETWORK得到的位置精度一般在500-1000米,GPS得到的精度一般在5-50米,基于这个属性我们可以对精度进行判断,以决定是否采用这个精度。
上面的代码中有1个isBetterLocation方法,这是用来判断获取的位置是否更好,这个方法来自于Dev Guide:
protected boolean isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > CHECK_INTERVAL;
boolean isSignificantlyOlder = timeDelta < -CHECK_INTERVAL;
boolean isNewer = timeDelta > 0;
// use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must
// be worse
} else if (isSignificantlyOlder) {
return false;
}
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return true;
}
return false;
}
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
我们可以看出上面方法不仅使用了Accuracy,还使用了时间进行判断,只要App需要定位,我们均可以直接使用上面的这个方法来对位置更新信息进行比较,提高精度。
一般来说,开发时我们先使用NETWORK来得到1个精度较差的位置,可以保存在数据库,一旦有精度更高的位置则覆盖原先的位置信息。