天天看點

高德地圖 android api 實作自動定位

未經允許,禁止轉載,違者必究!

浣熊我最近在研究高德地圖android api,看到第三章定位資訊後半部分關于“如何通過MyLocationOverlay 實作自動定位”的時候我淩亂了,寫得過于簡單,根本不知道如何操作。最後通過閱讀官方的示例代碼和在網上搜集大量資料實作了地圖自動定位的功能。

開發指南第三章定位資訊前半部分的代碼實作的功能是:當手機采集的地理位置(經緯度)發生改變時在界面上顯示出改變後的經緯度。如果開發過android原生定位程式的開發者應該對這部分代碼不陌生,中規中矩,先注冊位置監聽服務,然後當位置發生改變後出發onLocationChanged()方法。現在請在官網上下載下傳示例代碼,導入工程後開啟包com.amap.cn.apis.location中的MyLocation.java檔案,該檔案實作的主要功能是:初始化地圖并且實作首次定位,地圖會自動移動到定位點,我們一會便要基于這個檔案來完成地圖自動實時定位的功能。

看到這兒,有人可能想把MyLocation檔案中的内容與第三章給出的android原生定位子產品簡單整合。如果你的解決思路是:在onLocationChanged()方法中企圖在地圖上繪制出目前的位置,那麼就會遇到很大的麻煩。因為如果用高德地圖提供的api在地圖上繪制定位點的話一定要調用類MyLocationOverlay中的enableMyLocation()方法,根據官方參考資料,這個方法封裝了android原生的類LocationManager中的requestLocationUpdates()方法,是以你在寫onLocationChanged()方法前一定是已經調用了原生的類LocationManager中的requestLocationUpdates()方法,這樣一來造成了LocationManager在沒有removeUpdate前又進行了一次requestLocationUpdates,由此造成程式意外退出。

是以還是回到開發指南第三章,好好看看後半部分:如果想讓地圖跟随目前位置移動,需要繼承MyLocationOverlay 并實作其onLocationChanged()方法,調用MapView.getController().animateTo()方法移動地圖位置。官方使用者指南上的這句原話正是問題的正解,不過官網實在太坑爹,簡簡單單幾行文字和代碼,對于浣熊這種剛剛接觸地圖開發的小白來說實在是看得一頭霧水,還在一陣瞎折騰,終于解決了問題,是以共享出來,希望和我一樣的小白能夠少走些彎路。

我先把修改後的MyLocation.java檔案整個貼出來,在增加或改動的代碼前後均表明了注釋(不包括包的改動):“/*change start*/”和"/*change end*/"

/**
 * 使用MyLocationOverlay實作地圖自動定位
 * 實作初次定位使定位結果居中顯示
 */
public class MyLocation extends MapActivity {
	private MapView mMapView;
	private MapController mMapController;
	private GeoPoint point;
	
	/*change start*/
	private MyLocationOverlay_HX mLocationOverlay;
	/*change end*/
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mapview);
		mMapView = (MapView) findViewById(R.id.mapView);
		mMapView.setBuiltInZoomControls(true);  
		mMapController = mMapView.getController();  
		point = new GeoPoint((int) (39.90923 * 1E6),
				(int) (116.397428 * 1E6));  //用給定的經緯度構造一個GeoPoint,機關是微度 (度 * 1E6)
		mMapController.setCenter(point);  //設定地圖中心點
		mMapController.setZoom(15);
		
		/*change start*/
		mLocationOverlay = new MyLocationOverlay_HX(this, mMapView);
		/*change end*/
		
		mMapView.getOverlays().add(mLocationOverlay);
		//實作初次定位使定位結果居中顯示
		mLocationOverlay.runOnFirstFix(new Runnable() {
            public void run() {
            	handler.sendMessage(Message.obtain(handler, Constants.FIRST_LOCATION));
            }
        });
    }
    
    /*change start*/
    class MyLocationOverlay_HX extends MyLocationOverlay {

		public MyLocationOverlay_HX(Context arg0, MapView arg1) {
			super(arg0, arg1);
			// TODO Auto-generated constructor stub
		}
		
		public void onLocationChanged(Location location) {
			//Toast.makeText(getApplicationContext(), "Location Changed",Toast.LENGTH_LONG).show(); 
			
			point = new GeoPoint((int) (location.getLatitude() * 1E6),
					(int) (location.getLongitude() * 1E6));  //用給定的經緯度構造一個GeoPoint,機關是微度 (度 * 1E6)
			//mMapController.setCenter(point);  //設定地圖中心點
			mMapController.animateTo(point);
			super.onLocationChanged(location);
		}
    	
    }
    /*change end*/
    
    @Override
	protected void onPause() {
    	this.mLocationOverlay.disableMyLocation();
		super.onPause();
	}

	@Override
	protected void onResume() {
		this.mLocationOverlay.enableMyLocation();
		super.onResume();
	}

	private Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what == Constants.FIRST_LOCATION) {
				mMapController.animateTo(mLocationOverlay.getMyLocation());
			}
		}
    };
}