谈谈百度API的定位

     项目开发的过程中,可能需要用到定位。例如大众点评,一进入就开始定位。有时,你需要得到当前的Longitude、Latitude,或者Address,或者只是City。这时,你可能会使用Google的GPS模块进行定位。这种例子在网上是大把的,不过在谈及百度定位之前,咱们先回顾一下Google定位的做法。

     在Google的定位模块中,一般是GPS、Network或者基站方式。而且Google也提供了Criteria类给你定制你所需要的条件来进行定位,例如setAccuracy、setPowerRequirement、setAltitudeRequired等,然后由LocationManager 这个位置服务管理类getBestProvider获取当前最适合你的定位方式,然后getLastKnownLocation获得你要的Location。就这么简单!

     但是,这种方式经常没有那么理想(或者是我本身了解还不够全面的问题),而百度API这种“神级”的定位方式也应运而生。为什么称它神级,如果你使用过就应该比较清楚:基本只需要Network即可定位,如果需要精确定位则需要开启GPS,而且速度极快。但它最大的缺点是模式化。什么是模式化,就是写那个代码的时候,有些人都不知道到底是为什么,而且它提供的Lib的类都是木有注释,需要的话就得上官网看。

     不管怎样,下面给出一个例子代码:

/**
 * This Activity is mainly responsible for the preparation of the Navigation data 
 * and Location information.
 * @author XijieChen
 */
public class WelcomeActivity extends MapActivity {

	/**
	 * Regist this Listener when execute OnCreate and remove it when execute OnDestroy.
	 */
	private LocationListener mLocationListener = null;
	
	private MKSearch mMKSearch = null;
	
	/**
	 * These four variables are the location data which will be used in 
	 * all the application.
	 */
	private String CityAddress = null;
	private String subLongitude = null;
	private String subLatitude = null;
	private String cityName = null;
	
	LocationBean userLocation;
	
	/**
	 * This variable will equal to 1 when the Location file is exist and it will equal to 
	 * 0 on the contrary.
	 */
	private int Flag = 0;
	
	private SharedPreferences settings = null;
	
	
	/**
	 * This handler is mainly responsible for dealing with the message sent from threads. 
	 */
	Handler newhandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case Constant.WELCOME_DOWNLOADSUCCESS:
				Intent intent = new Intent();
				intent.setClass(WelcomeActivity.this, StartActivity.class);
				startActivity(intent);
				finish();//Finish the current activity.
				break;
			case Constant.WELCOME_STARTSEARCH:
				try {
					int Longitude = (int) (1000000 * Double.parseDouble(subLongitude));
					int Latitude = (int) (1000000 * Double.parseDouble(subLatitude));
					// Search the address in this GeoPoint.
					mMKSearch.reverseGeocode(new GeoPoint(Latitude, Longitude));
				} catch (Exception e) {
					e.printStackTrace();
				}
				break;
			case Constant.WELCOME_GETADDRESS:
				GetCityFromAddress getCity = new GetCityFromAddress(CityAddress);
				cityName = getCity.getCityFromAddress();
				if(Flag == 0) {
					userLocation.setLocationAddress(CityAddress);
					userLocation.setCity(cityName);
					WriteLocation write = new WriteLocation(userLocation,settings);
					write.WriteLocationData();
				}
				// Start the download thread to download the navigation data.
				DownLoadThread downLoadThread = new DownLoadThread(userLocation.getCity());
				downLoadThread.start();
				break;
			}
			super.handleMessage(msg);
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		setContentView(R.layout.activity_welcome);
		
		settings = getPreferences(Activity.MODE_APPEND);
		
		initLocationData(settings);
	}
	
	/**
	 * Initialize the Location data and judge whether the location SharedPreferences 
	 * is exist or not at the same time.
	 */
	private void initLocationData(SharedPreferences settings) {
		ReadLocation read = new ReadLocation(settings);
		
		if(read.GetLocation() != null) {
			userLocation = read.GetLocation();
			Flag = 1;//It means that the location SharedPreferences is exist.
			newhandler.obtainMessage(Constant.WELCOME_DOWNLOADSUCCESS).sendToTarget();
		} else {
			userLocation = new LocationBean();
			Flag = 0;//It means that the location SharedPreferences isn't exist.
			ApplicationData app = (ApplicationData) this.getApplication();
			if (app.mBMapMan == null) {
				app.mBMapMan = new BMapManager(getApplication());
				app.mBMapMan.init(app.mStrKey, new ApplicationData.MyGeneralListener());
			}
			app.mBMapMan.start();
			
			WRSearchListener wrtempListener = new WRSearchListener();
			mMKSearch = new MKSearch();
			mMKSearch.init(app.mBMapMan, wrtempListener);// To initialize the MKSearch
			
			mLocationListener = new LocationListener() {
				 
				public void onLocationChanged(Location location) {
					if (location != null) {
						StringBuilder longitude = new StringBuilder("" + location.getLongitude());
						subLongitude = (String) longitude.subSequence(0, 10);

						StringBuilder latitude = new StringBuilder("" + location.getLatitude());
						subLatitude = (String) latitude.subSequence(0, 9);
						
						userLocation.setLongitude(subLongitude);
						userLocation.setLatitude(subLatitude);
						newhandler.obtainMessage(Constant.WELCOME_STARTSEARCH).sendToTarget();
					}
				}
			};
		}
	}
	
	/**
	 * When the data download successfully, this thread is responsible for sending a
	 * DOWNLOADSUCCESS message to the newhandler.
	 */
	private class DownLoadThread extends Thread {
		
		private String cityString = null;
		
		public DownLoadThread(String city) {
			cityString = city;
		}
		
		@Override
		public void run() {
			DownLoadNaviData navidata = new DownLoadNaviData(WelcomeActivity.this,cityString);
			if (navidata.DownLoadData()) {
				newhandler.obtainMessage(Constant.WELCOME_DOWNLOADSUCCESS).sendToTarget();
			}
		}
	}
	
	protected void onPause() {
		if(Flag == 0) {
			ApplicationData app = (ApplicationData) this.getApplication();
			app.mBMapMan.getLocationManager().removeUpdates(mLocationListener);
			app.mBMapMan.stop();
		}
		ApplicationData.userLocation = userLocation;
		super.onPause();
	}

	 
	protected void onResume() {
		if(Flag == 0) {
			ApplicationData app = (ApplicationData) this.getApplication();
			app.mBMapMan.getLocationManager().requestLocationUpdates(mLocationListener);
			app.mBMapMan.start();
		}
		super.onResume();
	}
	
	protected void onDestroy() {
		ApplicationData app = (ApplicationData) this.getApplication();
		if (app.mBMapMan != null) {
			app.mBMapMan.destroy();
			app.mBMapMan = null;
		}
		super.onDestroy();
	}

	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		super.onBackPressed();
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
	/**
	 * Implement the MKSearchListener interface in order to search the address
	 * with the Logitude and the Latitude.
	 */
	public class WRSearchListener implements MKSearchListener {
		 
		public void onGetAddrResult(MKAddrInfo result, int iError) {
			if (result == null) {
				return;
			}
			StringBuffer sb = new StringBuffer();
			sb.append(result.strAddr);// The location depends on its Logitude and Latitude.
			CityAddress = sb.toString();
			
			newhandler.obtainMessage(Constant.WELCOME_GETADDRESS).sendToTarget();
		}

		public void onGetDrivingRouteResult(MKDrivingRouteResult result, int iError) {
		}

		public void onGetPoiResult(MKPoiResult result, int type, int iError) {
		}

		public void onGetTransitRouteResult(MKTransitRouteResult result, int iError) {
		}

		public void onGetWalkingRouteResult(MKWalkingRouteResult result, int iError) {
		}
	}
	
	
}

在程序中,在Application的OnCreate中你会发现这样的代码:mBMapMan.init(this.mStrKey, new MyGeneralListener());其中 MyGeneralListener是继承了MKGeneralListener,Key就是从http://dev.baidu.com/wiki/static/imap/key/上申请得到的。实际上,上面那个代码就是在注册一个BMapManager类对象。


1、BMapManager:注册该类,用于得到LocationManager,获取位置信息;

2、LocationListener:BMapManager要start前,需要requestLocationUpdates添加一个LocationListener。主要从该事件中onLocationChanged获取Location,从而获取Longitude、Latitude;(一般经纬度的获取是秒级的)

3、MKSearch:需要BMapManager的对象,以及一个实现了MKSearchListener的事件对象,进行init;

4、GeoPoint:使用你前面获得的Longitude、Latitude去new一个GeoPoint。值得注意的是,GeoPoint使用的经纬度必须是int型,所以首先必须将你的Longitude、Latitude转换为int。原因很简单,int运算速度快;

5、使用MKSearch的对象对一个GeoPoint进行reverseGeocode,这个时候,在你实现了MKSearchListener的事件对象中onGetAddrResult即可得到MKAddrInfo result,其中result就是你要的Address了。(一般情况下可以定位到市区,GPS下可以准确到街道门牌号,神级!!)


另外,百度这种定位强大在就算你使用它定位成功,其实你也不清楚里面的原理的,因为百度压根就没有告诉你,你会发现IDE中的类都是没有JavaDoc的。。。(或许是我学艺不精,还不理解吧,如果是这样,还望各位不吝指教)





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值