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

來源:互聯網
上載者:User

 

百度地圖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:/喎?http://www.bkjia.com/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();         @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//**使用地圖sdk前需先初始化BMapManager,這個必須在setContentView()先初始化mBMapManager = new BMapManager(this);//第一個參數是API key,   第二個參數是常用事件監聽,用來處理通常的網路錯誤,授權驗證錯誤等,你也可以不添加這個回調介面mBMapManager.init(LDtH1sVwr7kygaF0aTqaVwWU, new MKGeneralListener() {//授權錯誤的時候調用的回呼函數@Overridepublic void onGetPermissionState(int iError) {if (iError ==  MKEvent.ERROR_PERMISSION_DENIED) {showToast(API KEY錯誤, 請檢查!);            }}//一些網路狀態的錯誤處理回呼函數@Overridepublic 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() {@Overridepublic void onClick(View arg0) {requestLocation();}});}@Overrideprotected void onResume() {    //MapView的生命週期與Activity同步,當activity掛起時需調用MapView.onPause()mMapView.onResume();mBMapManager.start();//重新啟動super.onResume();}@Overrideprotected 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() {// * 點擊快顯視窗圖層回調的方法@Overridepublic 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); //開啟GPRSoption.setAddrType(all);//返回的定位結果包含地址資訊option.setCoorType(bd09ll);//返回的定位結果是百度經緯度,預設值gcj02option.setScanSpan(5000); //設定發起定位請求的間隔時間為5000msoption.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() {        // * 地圖移動完成時會回調此介面 方法@Overridepublic void onMapMoveFinish() {showToast(地圖移動完畢!);} //* 地圖載入完畢回調此介面方法@Overridepublic void onMapLoadFinish() {showToast(地圖載入完畢!);} //*  地圖完成帶動畫的操作(如: animationTo())後,此回調被觸發@Overridepublic void onMapAnimationFinish() {} //當調用過 mMapView.getCurrentMap()後,此回調會被觸發  可在此儲存至存放裝置@Overridepublic void onGetCurrentMap(Bitmap arg0) {} //* 點擊地圖上被標記的點回調此方法@Overridepublic void onClickMapPoi(MapPoi arg0) {if (arg0 != null){showToast(arg0.strText);}}});        }@Overridepublic 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();          }  @Overridepublic void setMarker(Drawable arg0) {super.setMarker(arg0);}              }      @Overrideprotected 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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.