編輯:關於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
/>
其中的meta-data問題:網上這樣說,大家記住就得了。。。。
因為單獨的定位sdk需要一個key值,而定位sdk的值又不像mapManager中可以直接賦值
所以就需要在注冊表單中注冊
運行圖示:
apk地址:http://pan.baidu.com/s/1hqqWSuw
部分內容摘自百度官方文檔。部分來自博客:http://blog.csdn.net/xiaanming/article/details/11380619
定位自己的位置基本就這些內容,出現的問題隨後會補充上。。今天就這樣吧。。吃飯去了。。
先看看我們的整個流程: 理解坐標系: 左側是Opengl默認的坐標系,右邊是典型的android設備屏幕的坐標系。左側的瘦瘦的
CircleImageView是github上一個第三方開源的實現圓形ImageView的項目。其在github上的項目主頁是:https://github.com/hd
在上一篇文章裡,我總結了一下自定義控件需要了解的基礎知識:View的繪制流程——《自定義控件知識儲備-View的繪制流程》。其中,在View的測量
引言我們在android的APP開發中有時候會碰到提供一個選項列表供用戶選擇的需求,如在投票類型的項目中,我們提供一些主題給用戶選擇,每個主題有若干選項,用戶對這些主題的