官方文檔:http://developer.baidu.com/map/sdkandev-6.htm#.E7.AE.80.E4.BB.8B3html
百度地圖SDK爲開發人員們提供了例如如下類型的地圖覆蓋物:java
個人位置圖層(MyLocationOverlay):用於顯示用戶當前位置的圖層(支持本身定義位置圖標);android
Poi搜索結果圖層(PoiOverlay):用於顯示興趣點搜索結果的圖層;git
路線圖層(RouteOverlay):公交、步行和駕車線路圖層,將公交、步行和駕車出行方案的路線及關鍵點顯示在地圖上(起、終點圖標用戶可本身定義);api
公交換乘圖層(TransitOverlay):公交換乘線路圖層,將某一特定地區的公交出行方案的路線及換乘位置顯示在地圖上(起、終點圖標用戶可本身定義);緩存
本身定義圖層(ItemizedOverlay):可將一個或多個興趣點繪製到地圖上,且支持本身定義圖標(支持動態更新Item位置、圖標);網絡
彈出窗圖層(PopupOverlay):在地圖上顯示一個彈出窗體;app
幾何圖形繪製圖層(GraphicsOverlay):用於繪製點、折線段、弧線、圓、矩形、多邊形等幾何圖形的圖層;異步
文字繪製圖層(TextOverlay):用於繪製文字的圖層。ide
圖片圖層(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文件複製到project的libs文件夾下
文件夾結構例如如下:
庫文件下載地址:http://pan.baidu.com/s/1ntNqKwp
二 . 佈局文件,一個百度地圖控件,加一個手動點擊實現定位的button
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <com.baidu.mapapi.map.MapView android:id="@+id/bmapView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" /> <Button android:id="@+id/request" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="10dp" android:layout_marginTop="10dip" android:background="@drawable/mylocation" /> </RelativeLayout>
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<OverlayItem>)效率更高 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("\nerror code : "); sb.append(location.getLocType()); sb.append("\nlatitude : "); sb.append(location.getLatitude()); sb.append("\nlontitude : "); sb.append(location.getLongitude()); sb.append("\nradius : "); sb.append(location.getRadius()); if (location.getLocType() == BDLocation.TypeGpsLocation){ sb.append("\nspeed : "); sb.append(location.getSpeed()); sb.append("\nsatellite : "); sb.append(location.getSatelliteNumber()); } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){ sb.append("\naddr : "); 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("[個人位置]\n" + 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的代碼凝視了,緣由是當我這兩個同一時候弄的時候會沒法給當前位置加入標記。。。這個問題稍後會獲得解決。
如下的佈局文件是彈出框的佈局,一個 很是easy的文件:pop_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/location_tips" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/location_tips" android:maxWidth="200.0dip" android:minWidth="40.0dip" android:textColor="@android:color/white" /> /> </RelativeLayout>
<span style="color:#ff6666;"> </span><span style="color:#333333;"> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.READ_LOGS" /></span>
當中的meta-data問題:網上這樣說,你們記住就得了。。。。
因爲單獨的定位sdk需要一個key值,而定位sdk的值又不像mapManager中可以直接賦值
因此就需要在註冊表單中註冊
執行圖示:
apk地址:http://pan.baidu.com/s/1hqqWSuw
部份內容摘自百度官方文檔。部分來自博客:http://blog.csdn.net/xiaanming/article/details/11380619
定位本身的位置基本就這些內容,出現的問題隨後會補充上。。今天就這樣吧。。吃飯去了。。