实现Android的不一样精度的定位(基于网络和GPS)转

【教程】实现Android的不一样精度的定位(基于网络和GPS)

 

 

在本教程中,我会分别讲述如何开启位置服务的监听,如何中止监听,如何得到不一样精度的定位,以及如何判判定位是否更精确。
Android中的定位服务的相关类基本上都在android.location包中,下面会按编写的顺序依次讲解。android

 

位置服务管理器(LocationManager)

首先,咱们须要1个LocationManager,考虑到它会被多个方法使用,咱们将它定义成Activity的Field。而后在onCreate方法中为它赋值。git

 

	//变量定义
	private LocationManager locationManager;
	//获得LocationManager
	locationManager = (LocationManager) this
			.getSystemService(Context.LOCATION_SERVICE)

 

开启位置服务的监听

有了LocationManager以后,咱们就能够开始监听位置的变化了。咱们使用LocationManager中的方法:
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
来设置监听器。
首先,咱们要注意到第1个参数,这个参数的值为2选1,分别是:LocationManager.NETWORK_PROVIDER和LocationManager.GPS_PROVIDER,前者用于移动网络中获取位置,精度较低但速度很快,后者使用GPS进行定位,精度很高但通常须要10-60秒时间才能开始第1次定位,若是是在室内则基本上没法定位。
这2种Provider本质上是互补的,在本教程中,咱们会同时开启2个监听,但基于移动网络的监听只会执行一次就会被中止,而基于GPS的监听则会一直持续下去,直至用户本身中止监听。
代码片断以下:
首先,咱们会声明1个监听器的内部类,这个类会同时用于2种模式的监听。还要声明1个变量,用于记录当前的位置。编程

private class MyLocationListner implements LocationListener{
	@Override
	public void onLocationChanged(Location location) {
		// Called when a new location is found by the location provider.
		Log.v("GPSTEST", "Got New Location of provider:"+location.getProvider());
		if(currentLocation!=null){
			if(isBetterLocation(location, currentLocation)){
				Log.v("GPSTEST", "It's a better location");
				currentLocation=location;
				showLocation(location);
			}
			else{
				Log.v("GPSTEST", "Not very good!");
			}
		}
		else{
			Log.v("GPSTEST", "It's first location");
			currentLocation=location;
			showLocation(location);
		}
		//移除基于LocationManager.NETWORK_PROVIDER的监听器
		if(LocationManager.NETWORK_PROVIDER.equals(location.getProvider())){
			locationManager.removeUpdates(this);
		}
	}

	//后3个方法此处不作处理
	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.v("GPSTEST","Latitude:"+location.getLatitude());
	//经度
	Log.v("GPSTEST","Longitude:+location.getLongitude());
	//精确度
	Log.v("GPSTEST","Accuracy:"+location.getAccuracy());
	//Location还有其它属性,请自行探索
}

开始监听的代码片断:网络

	private LocationListener gpsListener=null;
	private LocationListener networkListner=null;
	private void registerLocationListener(){
		networkListner=new MyLocationListner();
		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, networkListner);
		gpsListener=new MyLocationListner();
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, gpsListener);
	}

 

以上的代码仍是很易懂的吧,建立1个监听器对象,而后指定1个provider,而后requestLocationUpdates。在监听器中检查若是是NETWORK_PROVIDER,则取消监听,只留GPS的监听(在你的实际应用中能够根据状况来进行,由于GPS有可能会由于建筑的阻挡而暂时不工做)。less

位置精度的判断

在showLocation方法中,咱们打印了location的Accuracy属性,这就是精确度,通常来讲NETWORK获得的位置精度通常在500-1000米,GPS获得的精度通常在5-50米,基于这个属性咱们能够对精度进行判断,以决定是否采用这个精度。
你可能已经注意到上面的代码中有1个isBetterLocation方法,这是用来判断获取的位置是否更好,事实上这个方法来自于Dev Guide。咱们看下这个方法的内容:ide

 

private static final int CHECK_INTERVAL = 1000 * 30;
	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;

		// If it's been more than two minutes since the current location,
		// 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;
		}

		// Check whether the new location fix is more or less accurate
		int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
				.getAccuracy());
		boolean isLessAccurate = accuracyDelta > 0;
		boolean isMoreAccurate = accuracyDelta < 0;
		boolean isSignificantlyLessAccurate = accuracyDelta > 200;

		// Check if the old and new location are from the same provider
		boolean isFromSameProvider = isSameProvider(location.getProvider(),
				currentBestLocation.getProvider());

		// Determine location quality using a combination of timeliness and
		// accuracy
		if (isMoreAccurate) {
			return true;
		} else if (isNewer && !isLessAccurate) {
			return true;
		} else if (isNewer && !isSignificantlyLessAccurate
				&& isFromSameProvider) {
			return true;
		}
		return false;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
		if (provider1 == null) {
			return provider2 == null;
		}
		return provider1.equals(provider2);
	}

 

从代码中能够很清楚的看出判断位置是否“更好”的准则,不只使用了精度(getAccuracy()),还使用了时间进行判断。事实上除了在导航应用,其它的时候都可以直接使用上面的这个方法来对位置更新信息进行过滤,以减小不断更新界面而带来的性能损失。性能

结束监听

只须要调用LocationManager对象的removeUpdates(LocationListener listener)方法就能够中止监听。事实上,在以前的代码中你已经看到咱们移除了基于移动网络的监听器,下面的代码片断用于移除GPS监听器。ui

 

	if(gpsListener!=null){
		locationManager.removeUpdates(gpsListener);
		gpsListener=null;
	}

 

LocationManager的其它使用

这里还要介绍LocationManager中的几个方法:
getLastKnownLocation(String provider),用于获得上次定位时的最后位置,一般在应用刚启动时马上获得1个位置,这样应用看上去会比较快。
getBestProvider(Criteria criteria, boolean enabledOnly),根据条件(精度的高低,是否可以获得海拔等)以及当前是否开启,获得1个最好的位置Provider。看上去很美,但如今的Android系统中只有2个Provider,而大多数用户的GPS都是开启的,在仅仅是2选1的状况我想像不出这个方法的用途。而即使用户关闭了GPS,咱们也有能力帮他开启,用完了以后再关掉它。开启的方法见《进阶:如何编程实现开启或关闭GPS?》。this

总结

2个Provider提供了不一样精度的定位服务,咱们能够根据状况来使用。
通常来讲,先使用NETWORK来获得1个精度较差的位置,再使用GPS来获得更准确的位置。
在Android官方提供的Dev Guide中,提供了一个关于GPS使用的时间线,咱们来看一下
定位服务的通常时间线
归纳起来就是2句话:“快速反应,渐进式精确”。在实际的使用中也要根据本身的状况画1个时间线,好决定什么时候开始监听,什么时候结束监听。spa

 

本文收集自 http://www.learningandroid.net/blog/foundation/tutorial-location-ser

相关文章
相关标签/搜索