Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android應用中使用百度地圖API定位自己的位置(二)

Android應用中使用百度地圖API定位自己的位置(二)

編輯:關於Android編程

 

百度地圖SDK為開發者們提供了如下類型的地圖覆蓋物:

  • 我的位置圖層(MyLocationOverlay):用於顯示用戶當前位置的圖層(支持自定義位置圖標);

  • Poi搜索結果圖層(PoiOverlay):用於顯示興趣點搜索結果的圖層;

  • 路線圖層(RouteOverlay):公交、步行和駕車線路圖層,將公交、步行和駕車出行方案的路線及關鍵點顯示在地圖上(起、終點圖標用戶可自定義);

  • 公交換乘圖層(TransitOverlay):公交換乘線路圖層,將某一特定地區的公交出行方案的路線及換乘位置顯示在地圖上(起、終點圖標用戶可自定義);

  • 自定義圖層(ItemizedOverlay):可將一個或多個興趣點繪制到地圖上,且支持自定義圖標(支持動態更新Item位置、圖標);

  • 彈出窗圖層(PopupOverlay):在地圖上顯示一個彈出窗口;

  • 幾何圖形繪制圖層(GraphicsOverlay):用於繪制點、折線段、弧線、圓、矩形、多邊形等幾何圖形的圖層;

  • 文字繪制圖層(TextOverlay):用於繪制文字的圖層。

  • 圖片圖層(GroundOverlay):用於展示用戶傳入圖片的圖層。

  • 全景圖圖層(PanoramaOverlay):在全景圖內標繪興趣點,支持自定義圖標樣式。

    注:除彈出窗圖層外,其他各個圖層均已實現多實例。全景圖圖層是針對全景圖所使用的特殊圖層。

    MapView使用一個List管理覆蓋物,通過向MapView.getOverlays() add或remove上述類或其基類的實例即可向地圖添加或刪除覆蓋物。在更新地圖覆蓋物後,需調用MapView.refresh() 使更新生效。

     

     

    定位原理

    使用百度Android定位SDK必須注冊GPS和網絡使用權限。定位SDK采用GPS、基站、Wi-Fi信號進行定位。當應用程序向定位SDK發起定位請求時,定位SDK會根據應用的定位因素(GPS、基站、Wi-Fi信號)的實際情況(如是否開啟GPS、是否連接網絡、是否有信號等)來生成相應定位依據進行定位。
    用戶可以設置滿足自身需求的定位依據:
    若用戶設置GPS優先,則優先使用GPS進行定位,如果GPS定位未打開或者沒有可用位置信息,且網絡連接正常,定位SDK則會返回網絡定位(即Wi-Fi與基站)的最優結果。為了使獲得的網絡定位結果更加精確,請打開手機的Wi-Fi開關。

     

    下面我們將利用 MyLocationOverlay和 PopupOverlay 這兩個類

     

    一 . 導入庫文件

    在使用百度定位SDKv4.0之前,我們要下載最新的庫文件,下載地址:點擊下載相關庫文件,將liblocSDK4.so文件拷貝到libs/armeabi目錄下。將locSDK4.0.jar文件拷貝到工程的libs目錄下

    目錄結構如下:

    庫文件下載地址:http:/喎?/kf/ware/vc/" target="_blank" class="keylink">vcGFuLmJhaWR1LmNvbS9zLzFudE5xS3dwPC9wPgo8cD62/iAuILK8vtbOxLz+o6zSu7j2sNm2yLXYzby/2Lz+o6y809K7uPbK1ravteO798q1z9a2qM67tcSwtMWlPC9wPgo8cD4mbmJzcDs8L3A+CjxwcmUgY2xhc3M9"brush:java;">
    然後是主 Activity

     

     

    package com.majianjie.baidumap;
    
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.View.MeasureSpec;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.baidu.location.BDLocation;
    import com.baidu.location.BDLocationListener;
    import com.baidu.location.LocationClient;
    import com.baidu.location.LocationClientOption;
    import com.baidu.mapapi.BMapManager;
    import com.baidu.mapapi.MKGeneralListener;
    import com.baidu.mapapi.map.LocationData;
    import com.baidu.mapapi.map.MKEvent;
    import com.baidu.mapapi.map.MKMapViewListener;
    import com.baidu.mapapi.map.MapController;
    import com.baidu.mapapi.map.MapPoi;
    import com.baidu.mapapi.map.MapView;
    import com.baidu.mapapi.map.MyLocationOverlay;
    import com.baidu.mapapi.map.PopupClickListener;
    import com.baidu.mapapi.map.PopupOverlay;
    import com.baidu.platform.comapi.basestruct.GeoPoint;
    import com.example.baidumap.R;
    
    public class MainActivity extends Activity {
    
    	//聲明控件
    		private Button request;
    	
    		private Toast mToast=null;
    		private BMapManager mBMapManager=null;
    		private MapView mMapView = null;			//MapView 是地圖主控件
    		private MapController mMapController = null;//用MapController完成地圖控制
    		
    		private LocationClient mLocClient; 
    		 public LocationData mLocData = null;
    		 
    		private LocationOverlay myLocationOverlay = null;//定位圖層
    		private boolean isRequest = false;//是否手動觸發請求定位  
    	    private boolean isFirstLoc = true;//是否首次定位  
    	   
    	    private PopupOverlay mPopupOverlay  = null;//彈出泡泡圖層,浏覽節點時使用
    	    private View viewCache=null;
    	    public BDLocation location = new BDLocation(); 
    	    
    	    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		
    		//**使用地圖sdk前需先初始化BMapManager,這個必須在setContentView()先初始化
    				mBMapManager = new BMapManager(this);
    				//第一個參數是API key,   第二個參數是常用事件監聽,用來處理通常的網絡錯誤,授權驗證錯誤等,你也可以不添加這個回調接口
    				mBMapManager.init(LDtH1sVwr7kygaF0aTqaVwWU, new MKGeneralListener() {
    					//授權錯誤的時候調用的回調函數
    					@Override
    					public void onGetPermissionState(int iError) {
    						if (iError ==  MKEvent.ERROR_PERMISSION_DENIED) {
    							showToast(API KEY錯誤, 請檢查!);
    			            }
    					}
    					//一些網絡狀態的錯誤處理回調函數
    					@Override
    					public void onGetNetworkState(int iError) {
    						if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
    							Toast.makeText(getApplication(), 您的網絡出錯啦!, Toast.LENGTH_LONG).show();
    			            }
    					}
    				});
    		//初始化
    		init();
    		//單擊事件
    		click();
    	}
    
    	//* 顯示Toast消息 
        private void showToast(String msg){  
            if(mToast == null){  
                mToast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);  
            }else{  
                mToast.setText(msg);  
                mToast.setDuration(Toast.LENGTH_SHORT);
            }  
            mToast.show();  
        } 
    	private void click() {
    		request.setOnClickListener(new View.OnClickListener() {
    			@Override
    			public void onClick(View arg0) {
    				requestLocation();
    			}
    		});
    		
    	}
    	@Override
    	protected void onResume() {
        	//MapView的生命周期與Activity同步,當activity掛起時需調用MapView.onPause()
    		mMapView.onResume();
    		mBMapManager.start();//重新啟動
    		super.onResume();
    	}
    	@Override
    	protected void onPause() {
    		//MapView的生命周期與Activity同步,當activity掛起時需調用MapView.onPause()
    		mMapView.onPause();
    		super.onPause();
    	}
    
    	private void init() {
    		//使用自定義的title,注意順序
    		setContentView(R.layout.activity_main);   //activity的布局                   //這裡是添加自己定義的titlebtn.xml
    		
    		//通過id找到他們
    		mMapView = (com.baidu.mapapi.map.MapView) findViewById(R.id.bmapView);
    		mMapController=mMapView.getController(); //獲取地圖控制器
    		mMapController.enableClick(true);   //設置地圖是否響應點擊事件
    		request=(Button)findViewById(R.id.request);
    		
    		
    		viewCache = LayoutInflater.from(this).inflate(R.layout.pop_layout, null);
    		mPopupOverlay= new PopupOverlay(mMapView, new PopupClickListener() {// * 點擊彈出窗口圖層回調的方法
    			@Override
    			public void onClickedPopup(int arg0) {
    				//隱藏彈出窗口圖層  
                    mPopupOverlay.hidePop();  
    				
    			}
    		});
    		
    		
            mMapController.enableClick(true);                //*  設置地圖是否響應點擊事件  . 
            mMapController.setZoom(12);					// * 設置地圖縮放級別
            mMapView.setBuiltInZoomControls(true);      // * 顯示內置縮放控件
            mMapView.setTraffic(true);
            
            mLocData = new LocationData();
            
    		mLocClient = new LocationClient(getApplicationContext());  //   * 定位SDK的核心類
    		 //實例化定位服務,LocationClient類必須在主線程中聲明  
            mLocClient.registerLocationListener(new BDLocationListenerImpl());//注冊定位監聽接口
        	/**
    		 * 設置定位參數
    		 */
    		LocationClientOption option = new LocationClientOption();
    		option.setOpenGps(true); //打開GPRS
    		option.setAddrType(all);//返回的定位結果包含地址信息
    		option.setCoorType(bd09ll);//返回的定位結果是百度經緯度,默認值gcj02
    		option.setScanSpan(5000); //設置發起定位請求的間隔時間為5000ms
    		option.disableCache(false);//禁止啟用緩存定位
    		option.setPoiNumber(5);    //最多返回POI個數   
    		option.setPoiDistance(1000); //poi查詢距離        
    		option.setPoiExtraInfo(true);  //是否需要POI的電話和地址等詳細信息        
    		
    		mLocClient.setLocOption(option);
    		mLocClient.start();  //	調用此方法開始定位
            
    		myLocationOverlay = new LocationOverlay(mMapView);//定位圖層初始化
    		
    		 //將定位數據設置到定位圖層裡  
            
            myLocationOverlay.setMarker(getResources().getDrawable(R.drawable.set));
    	    //添加定位圖層
    	    mMapView.getOverlays().add(myLocationOverlay);
    	    myLocationOverlay.enableCompass();
            
            //更新圖層數據執行刷新後生效  
            mMapView.refresh();  
             
      /*  	
            //准備要添加的Overlay  
            double mLat1 = 39.910159;  
            double mLon1 = 119.544697;  
            
            // 用給定的經緯度構造GeoPoint,單位是微度 (度 * 1E6)  
            GeoPoint p1 = new GeoPoint((int) (mLat1 * 1E6), (int) (mLon1 * 1E6));  
          
            //准備overlay圖像數據,根據實情情況修復  
            Drawable mark= getResources().getDrawable(R.drawable.set);  
            //用OverlayItem准備Overlay數據  
            OverlayItem item1 = new OverlayItem(p1,item1,item1);  
            //使用setMarker()方法設置overlay圖片,如果不設置則使用構建ItemizedOverlay時的默認設置  
           
               
            //創建IteminizedOverlay  
            CustomItemizedOverlay itemOverlay = new CustomItemizedOverlay(mark, mMapView);  
            //將IteminizedOverlay添加到MapView中  
              
            mMapView.getOverlays().clear();  
            mMapView.getOverlays().add(itemOverlay);  
               
            		//現在所有准備工作已准備好,使用以下方法管理overlay.  
            		//添加overlay, 當批量添加Overlay時使用addItem(List)效率更高  
            itemOverlay.addItem(item1);  
    		      //刪除overlay .  
    		      //itemOverlay.removeItem(itemOverlay.getItem(0));  
    		      //mMapView.refresh();  
    		      //清除overlay  
    		      // itemOverlay.removeAll();  
    		      // mMapView.refresh();  
            mMapView.refresh(); 
       */    
            
            
            // mMapController.setCenter(p1);        
            
            mMapView.regMapViewListener(mBMapManager, new MKMapViewListener() {
            	// * 地圖移動完成時會回調此接口 方法
    			@Override
    			public void onMapMoveFinish() {
    				showToast(地圖移動完畢!);
    			}
    			 //* 地圖加載完畢回調此接口方法
    			@Override
    			public void onMapLoadFinish() {
    				showToast(地圖載入完畢!);
    			}
    			 //*  地圖完成帶動畫的操作(如: animationTo())後,此回調被觸發
    			@Override
    			public void onMapAnimationFinish() {
    				
    			}
    			 //當調用過 mMapView.getCurrentMap()後,此回調會被觸發  可在此保存截圖至存儲設備
    			@Override
    			public void onGetCurrentMap(Bitmap arg0) {
    			}
    			 //* 點擊地圖上被標記的點回調此方法
    			@Override
    			public void onClickMapPoi(MapPoi arg0) {
    				if (arg0 != null){
    					showToast(arg0.strText);
    				}
    			}
    		});
            
    	}
    
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		super.onCreateOptionsMenu(menu);
    		CreateMenu(menu);
    		return true;
    	}
    
    	private void CreateMenu(Menu menu){
    		MenuItem mnu1 =menu.add(0,0,0,顯示衛星地圖);
    		{
    			mnu1.setAlphabeticShortcut('a');//設置快捷鍵
    			//mnu1.serIcon(R.drawable.icon);//設置圖片
    		}
    		MenuItem mnu2 =menu.add(0,1,1,顯示街道地圖);
    		{
    			mnu2.setAlphabeticShortcut('b');//設置快捷鍵
    			//mnu1.serIcon(R.drawable.icon);//設置圖片
    		}
    		MenuItem mnu3 =menu.add(0,2,2,3D地圖);
    		{
    			mnu3.setAlphabeticShortcut('c');//設置快捷鍵
    			//mnu1.serIcon(R.drawable.icon);//設置圖片
    		}
    	}
    	
    	@Override
        public boolean onOptionsItemSelected(MenuItem item) {
            if(item.getItemId() == 0){
            	 mMapView.setSatellite(true);				//設置顯示為衛星地圖:
            	 mMapView.setTraffic(false);	
            }else if(item.getItemId() == 1){
            	 mMapView.setTraffic(true);					//顯示街道地圖
            	 mMapView.setSatellite(false);
            }else if(item.getItemId() == 2){
            	 //mMapView.se
            } 
            return true;
        }
    
    
    	public class BDLocationListenerImpl implements BDLocationListener {  
           //  * 接收異步返回的定位結果,參數是BDLocation類型參數 
            @Override  
            public void onReceiveLocation(BDLocation location) {  
                if (location == null) {  
                    return;  
                }  
        /*          
                StringBuffer sb = new StringBuffer(256);  
                  sb.append(time : );  
                  sb.append(location.getTime());  
                  sb.append(
    error code : );  
                  sb.append(location.getLocType());  
                  sb.append(
    latitude : );  
                  sb.append(location.getLatitude());  
                  sb.append(
    lontitude : );  
                  sb.append(location.getLongitude());  
                  sb.append(
    radius : );  
                  sb.append(location.getRadius());  
                  if (location.getLocType() == BDLocation.TypeGpsLocation){  
                       sb.append(
    speed : );  
                       sb.append(location.getSpeed());  
                       sb.append(
    satellite : );  
                       sb.append(location.getSatelliteNumber());  
                       } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){  
                       sb.append(
    addr : );  
                       sb.append(location.getAddrStr());  
                    }   
          */        
                MainActivity.this.location = location;  
                  
                mLocData.latitude = location.getLatitude();  
                mLocData.longitude = location.getLongitude();  
                //如果不顯示定位精度圈,將accuracy賦值為0即可  
                mLocData.accuracy = location.getRadius();  
                mLocData.direction = location.getDerect();  
                  
              //將定位數據設置到定位圖層裡
                myLocationOverlay.setData(mLocData);
                //更新圖層數據執行刷新後生效
                mMapView.refresh();
                
                if(isFirstLoc || isRequest){  
                    //將給定的位置點以動畫形式移動至地圖中心  
                    mMapController.animateTo(new GeoPoint(  
                            (int) (location.getLatitude() * 1e6), (int) (location.getLongitude() * 1e6)));  
                    showPopupOverlay(location);  //載入時候就彈出
                    isRequest = false;  
                }  
                isFirstLoc = false;  
                  
            }  
      
           // 接收異步返回的POI查詢結果,參數是BDLocation類型參數 
            @Override  
            public void onReceivePoi(BDLocation poiLocation) {  
                  
            }  
      
        }  
        
    	private void requestLocation() {
    		isRequest = true;  
            if(mLocClient != null && mLocClient.isStarted()){  
                showToast(正在定位......);  
                mLocClient.requestLocation();  
            }  
    	}
        
    	//繼承MyLocationOverlay重寫dispatchTap方法  
        private class LocationOverlay extends MyLocationOverlay{  
      
            public LocationOverlay(MapView arg0) {  
                super(arg0);  
            }  
           //  * 在“我的位置”坐標上處理點擊事件。 
            @Override  
            protected boolean dispatchTap() {  
                //點擊我的位置顯示PopupOverlay  
                showPopupOverlay(location);  
                return super.dispatchTap();  
            }  
    		@Override
    		public void setMarker(Drawable arg0) {
    			super.setMarker(arg0);
    		}
    		
              
        }  
    	
        @Override
    	protected void onDestroy() {
    		//MapView的生命周期與Activity同步,當activity銷毀時需調用MapView.destroy()
    		mMapView.destroy();
    		
    		//退出應用調用BMapManager的destroy()方法
    		if(mBMapManager != null){
    			mBMapManager.destroy();
    			mBMapManager = null;
    		}
    		
    		//退出時銷毀定位
            if (mLocClient != null){
                mLocClient.stop();
            }
    		
    		super.onDestroy();
    	}
        
          
         //* 顯示彈出窗口圖層PopupOverlay 
        private void showPopupOverlay(BDLocation location){  
             TextView popText = ((TextView)viewCache.findViewById(R.id.location_tips));  
             popText.setText([我的位置]
     + location.getAddrStr());  
             mPopupOverlay.showPopup(getBitmapFromView(popText),  
                        new GeoPoint((int)(location.getLatitude()*1e6), (int)(location.getLongitude()*1e6)),  
                        15);  
               
        }  
        
        // * 將View轉換成Bitmap的方法 
        public static Bitmap getBitmapFromView(View view) {  
            view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));  
            view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());  
            view.buildDrawingCache();  
            Bitmap bitmap = view.getDrawingCache();  
            return bitmap;  
        }  
          
        
    }
    

    大家注意:這裡我把上一次的添加marker的代碼注釋了,原因是當我這兩個同時弄的時候會無法給當前位置添加標記。。。這個問題稍後會得到解決。

    下面的布局文件是彈出框的布局,一個 很簡單的文件:pop_layout.xml

    
    
    	
             />  
           
    

     

     

     

     

    • LocationClient 定位SDK的核心類,LocationClient類必須在主線程中聲明。需要Context類型的參數。Context需要時全進程有效的context,推薦用getApplicationConext獲取全進程有效的context,我們調用registerLocationListener(BDLocationListener)方法來注冊定位監聽接口,BDLocationListener裡面有兩個方法,onReceiveLocation()(接收異步返回的定位結果),onReceivePoi()(接收異步返回的POI查詢結果,POI是“Point of Interest”的縮寫,可以翻譯成“信息點”,每個POI包含四方面信息,名稱、類別、經度、緯度、附近的酒店、飯店,商鋪等信息。我們可以叫它為“導航地圖信息”,導航地圖數據是整個導航產業的基石),我們這裡只需要重寫onReceiveLocation就行了BDLocation 封裝了定位SDK的定位結果,在BDLocationListener的onReceive方法中獲取。通過該類用戶可以獲取error code,位置的坐標,精度半徑,地址等信息,對於其getLocType ()方法獲取的error code一些情況
      1. 61 : GPS定位結果62 : 掃描整合定位依據失敗。此時定位結果無效。63 : 網絡異常,沒有成功向服務器發起請求。此時定位結果無效。65 : 定位緩存的結果。66 : 離線定位結果。通過requestOfflineLocaiton調用時對應的返回結果67 : 離線定位失敗。通過requestOfflineLocaiton調用時對應的返回結果68 : 網絡連接失敗時,查找本地離線定位時對應的返回結果161: 表示網絡定位結果162~167: 服務端定位失敗
        • LocationClientOption 用來設置定位SDK的定位方式,比如設置打開GPS,設置是否需要地址信息,設置發起定位請求的間隔時間等等,參數設置完後調用LocationClient 的setLocOption方法LocationOverlay MyLocationOverlay的子類,重寫裡面的dispatchTap()方法,顯示彈出窗口圖層PopupOverlay,調用mMapView.getOverlays().add(myLocationOverlay)就將我的位置圖層添加到地圖裡面PopupOverlay 彈出圖層,這個類還是比較簡單,裡面只有三個方法,hidePop() (隱藏彈出圖層)showPopup(Bitmap pop, GeoPoint point, int yOffset) (顯示彈出圖層)和showPopup顯示多張圖片的重載方法,由於showPopup方法只接受Bitmap對象,所以我們必須將我們的彈出圖層View對象轉換成Bitmap對象,我們調用getBitmapFromView方法就實現這一轉換BDLocationListener接口的onReceiveLocation(BDLocation location) 方法我還要重點講解下,我們會發現onReceiveLocation方法會反復執行,他執行的間隔跟LocationClientOption類的setScanSpan()方法設定的值有關,我們設定的是5000毫秒,則onReceiveLocation方法每隔5秒執行一次,注意,當我們設定的值大於1000(ms),定位SDK內部使用定時定位模式。調用requestLocation( )後,每隔設定的時間,定位SDK就會進行一次定位。如果定位SDK根據定位依據發現位置沒有發生變化,就不會發起網絡請求,返回上一次定位的結果;如果發現位置改變,就進行網絡請求進行定位,得到新的定位結果。如果你只需要定位一次的話,這個設置小於1000,或者不用設置就可以了,定時定位時,調用一次requestLocation,會定時監聽到定位結果 四 . 在運行程序之前,我們還必須在AndroidManifest.xml進行相關配置和權限的聲明

           

              
              
              
              
              
              
              
              
              
              

          還有很重要的一點就是在AndroidManifest.xml中添加下面的內容

           

           

          android:name=com.baidu.location.f
          android:enabled=true
          android:process=:remote >



          android:name=com.baidu.lbsapi.API_KEY
          android:value=6KOX4mXHeBRzgriV6OP1T2Hw
          />

          其中的meta-data問題:網上這樣說,大家記住就得了。。。。

          因為單獨的定位sdk需要一個key值,而定位sdk的值又不像mapManager中可以直接賦值
          所以就需要在注冊表單中注冊

          運行圖示:

          \ apk地址:http://pan.baidu.com/s/1hqqWSuw

          部分內容摘自百度官方文檔。部分來自博客:http://blog.csdn.net/xiaanming/article/details/11380619

          定位自己的位置基本就這些內容,出現的問題隨後會補充上。。今天就這樣吧。。吃飯去了。。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved