百度地图SDK2.4.1 中实现路径规划

在做项目的时候,刚开始做的路径规划是驾车路径规划,路径规划使用的是MKSearch类,在初始化的时候要传入监听器和BMapManager和MKSearchListener这个监听器,然后再这个监听器里面进行路径规划结果的监听,因为我做的是驾车的路径规划,所以我调用的是传入参数后发现onGetDrivingRouteResult回调函数没有被调用,这个东西折腾了好长时间,我一直以为我是前面什么地方写错了,但是我仔细一看onGetBusDetailResult方法被调用了,这个是搜索公交i路径的回调方法,然后我就尝试调用公交搜索,发现还是调用了onGetBusDetailResult方法,这个是百度地图2.4.1的bug,没办法,只能改用步行搜索,但是还是不行,后来我才发现,百度又有一个bug,那就是他把经纬度搞反了。


刚开始我传入地点名路径规划就能成功,但是传入坐标,无论如何也不会成功,然后我就从网上看到了下面坐标的写法。

					
									 start.pt = new GeoPoint((int) (31.205889 * 1E6), (int)
				 (121.637942 * 1E6));
				 end.pt = new GeoPoint( (int) (31.243319 * 1E6), (int)
				 (121.509075 * 1E6));
这个地点就是就可以导航,因为他把经纬度写反了,但是,的确只有这样才有效果。但是服务器给我的是反坐标,本地定位得到的是正坐标,这就导致了我怎么改才都错,蒸腾了好久才发现原因。这个教训要吸取一下。

由于这个项目是商业项目,不便上传源码,所以我写了一个独立的demo供大家学习,这个demo参考的是百度2.4.1的demo的写法。

这个是用来初始化BMapManager类的

package com.liran.completeroutedemo;


import android.app.Application;
import android.content.Context;
import android.widget.Toast;

import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.MKGeneralListener;
import com.baidu.mapapi.map.MKEvent;


public class DemoApplication extends Application {
	
    private static DemoApplication mInstance = null;
    public boolean m_bKeyRight = true;
    BMapManager mBMapManager = null;

	
	@Override
    public void onCreate() {
	    super.onCreate();
		mInstance = this;
		System.out.println("application 的 oncreate");
		initEngineManager(this);
	}
	
	public void initEngineManager(Context context) {
        if (mBMapManager == null) {
            mBMapManager = new BMapManager(context);
        }

        if (!mBMapManager.init(new MyGeneralListener())) {
            Toast.makeText(DemoApplication.getInstance().getApplicationContext(), 
                    "BMapManager  初始化错误!", Toast.LENGTH_LONG).show();
        }
	}
	
	public static DemoApplication getInstance() {
		return mInstance;
	}
	
	
	// 常用事件监听,用来处理通常的网络错误,授权验证错误等
    static class MyGeneralListener implements MKGeneralListener {
        
        @Override
        public void onGetNetworkState(int iError) {
            if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
                Toast.makeText(DemoApplication.getInstance().getApplicationContext(), "您的网络出错啦!",
                    Toast.LENGTH_LONG).show();
            }
            else if (iError == MKEvent.ERROR_NETWORK_DATA) {
                Toast.makeText(DemoApplication.getInstance().getApplicationContext(), "输入正确的检索条件!",
                        Toast.LENGTH_LONG).show();
            }
            // ...
        }

        @Override
        public void onGetPermissionState(int iError) {
        	//非零值表示key验证未通过
            if (iError != 0) {
                //授权Key错误:
                Toast.makeText(DemoApplication.getInstance().getApplicationContext(), 
                        "请在 DemoApplication.java文件输入正确的授权Key,并检查您的网络连接是否正常!error: "+iError, Toast.LENGTH_LONG).show();
                DemoApplication.getInstance().m_bKeyRight = false;
            }
            else{
            	DemoApplication.getInstance().m_bKeyRight = true;
            	Toast.makeText(DemoApplication.getInstance().getApplicationContext(), 
                        "key认证成功", Toast.LENGTH_LONG).show();
            }
        }
    }
}


下面便是主要功能代码

package com.liran.completeroutedemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.map.MKEvent;
import com.baidu.mapapi.map.MKMapTouchListener;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.PopupClickListener;
import com.baidu.mapapi.map.PopupOverlay;
import com.baidu.mapapi.map.RouteOverlay;
import com.baidu.mapapi.map.TransitOverlay;
import com.baidu.mapapi.search.MKAddrInfo;
import com.baidu.mapapi.search.MKBusLineResult;
import com.baidu.mapapi.search.MKDrivingRouteResult;
import com.baidu.mapapi.search.MKPlanNode;
import com.baidu.mapapi.search.MKPoiResult;
import com.baidu.mapapi.search.MKRoute;
import com.baidu.mapapi.search.MKSearch;
import com.baidu.mapapi.search.MKSearchListener;
import com.baidu.mapapi.search.MKShareUrlResult;
import com.baidu.mapapi.search.MKSuggestionResult;
import com.baidu.mapapi.search.MKTransitRouteResult;
import com.baidu.mapapi.search.MKWalkingRouteResult;
import com.baidu.platform.comapi.basestruct.GeoPoint;
/**
 * 此demo用来展示如何进行驾车、步行、公交路线搜索并在地图使用RouteOverlay、TransitOverlay绘制
 * 同时展示如何进行节点浏览并弹出泡泡
 *
 */
public class MainActivity extends Activity {

	//UI相关
	Button mBtnDrive = null;	// 驾车搜索
	Button mBtnTransit = null;	// 公交搜索
	Button mBtnWalk = null;	// 步行搜索
	Button mBtnCusRoute = null; //自定义路线
	Button mBtnCusIcon = null ; //自定义起终点图标
	
	//浏览路线节点相关
	Button mBtnPre = null;//上一个节点
	Button mBtnNext = null;//下一个节点
	int nodeIndex = -2;//节点索引,供浏览节点时使用
	MKRoute route = null;//保存驾车/步行路线数据的变量,供浏览节点时使用
	TransitOverlay transitOverlay = null;//保存公交路线图层数据的变量,供浏览节点时使用
	RouteOverlay routeOverlay = null; 
	boolean useDefaultIcon = false;
	int searchType = -1;//记录搜索的类型,区分驾车/步行和公交
	private PopupOverlay   pop  = null;//弹出泡泡图层,浏览节点时使用
	private TextView  popupText = null;//泡泡view
	private View viewCache = null;
	
	//地图相关,使用继承MapView的MyRouteMapView目的是重写touch事件实现泡泡处理
	//如果不处理touch事件,则无需继承,直接使用MapView即可
	MapView mMapView = null;	// 地图View
	//搜索相关
	MKSearch mSearch = null;	// 搜索模块,也可去掉地图模块独立使用
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		/**
         * 使用地图sdk前需先初始化BMapManager.
         * BMapManager是全局的,可为多个MapView共用,它需要地图模块创建前创建,
         * 并在地图地图模块销毁后销毁,只要还有地图模块在使用,BMapManager就不应该销毁
         */
        DemoApplication app = (DemoApplication)this.getApplication();
        if (app.mBMapManager == null) {
            app.mBMapManager = new BMapManager(getApplicationContext());
            /**
             * 如果BMapManager没有初始化则初始化BMapManager
             */
            app.mBMapManager.init(new DemoApplication.MyGeneralListener());
        }
		setContentView(R.layout.activity_main);
		CharSequence titleLable="路线规划功能";
        setTitle(titleLable);
        
		//初始化地图
        mMapView = (MapView)findViewById(R.id.bmapView);
        mMapView.setBuiltInZoomControls(false);
        mMapView.getController().setZoom(12);
        mMapView.getController().enableClick(true);

        //初始化按键
        mBtnDrive = (Button)findViewById(R.id.drive);
        mBtnTransit = (Button)findViewById(R.id.transit);
        mBtnWalk = (Button)findViewById(R.id.walk);
        mBtnPre = (Button)findViewById(R.id.pre);
        mBtnNext = (Button)findViewById(R.id.next);
        mBtnCusRoute = (Button)findViewById(R.id.custombutton);
        mBtnCusIcon = (Button)findViewById(R.id.customicon);
        mBtnPre.setVisibility(View.INVISIBLE);
		mBtnNext.setVisibility(View.INVISIBLE);
	    
        //按键点击事件
        OnClickListener clickListener = new OnClickListener(){
			public void onClick(View v) {
				//发起搜索
				SearchButtonProcess(v);
			}
        };
        OnClickListener nodeClickListener = new OnClickListener(){
			public void onClick(View v) {
				//浏览路线节点
				//nodeClick(v);
			}
        };
        OnClickListener customClickListener = new OnClickListener(){
			public void onClick(View v) {
				//自设路线绘制示例
			//	intentToActivity();
				
			}
        };
        
        OnClickListener changeRouteIconListener = new OnClickListener(){

			@Override
			public void onClick(View arg0) {
				changeRouteIcon();
			}
        	
        };
        
        mBtnDrive.setOnClickListener(clickListener); 
        mBtnTransit.setOnClickListener(clickListener); 
        mBtnWalk.setOnClickListener(clickListener);
        mBtnPre.setOnClickListener(nodeClickListener);
        mBtnNext.setOnClickListener(nodeClickListener);
        mBtnCusRoute.setOnClickListener(customClickListener);
        mBtnCusIcon.setOnClickListener(changeRouteIconListener);
        //创建 弹出泡泡图层
        createPaopao();
       
        //地图点击事件处理
        mMapView.regMapTouchListner(new MKMapTouchListener(){

			@Override
			public void onMapClick(GeoPoint point) {
			  //在此处理地图点击事件 
			  //消隐pop
			  if ( pop != null ){
				  pop.hidePop();
			  }
			}

			@Override
			public void onMapDoubleClick(GeoPoint point) {
				
			}

			@Override
			public void onMapLongClick(GeoPoint point) {
				
			}
        	
        });
        
        // 初始化搜索模块,注册事件监听
        mSearch = new MKSearch();
        mSearch.init(app.mBMapManager, new MKSearchListener(){

			public void onGetDrivingRouteResult(MKDrivingRouteResult res,
					int error) {
				//起点或终点有歧义,需要选择具体的城市列表或地址列表
				if (error == MKEvent.ERROR_ROUTE_ADDR){
					//遍历所有地址
//					ArrayList stPois = res.getAddrResult().mStartPoiList;
//					ArrayList enPois = res.getAddrResult().mEndPoiList;
//					ArrayList stCities = res.getAddrResult().mStartCityList;
//					ArrayList enCities = res.getAddrResult().mEndCityList;
					return;
				}
				// 错误号可参考MKEvent中的定义
				if (error != 0 || res == null) {
					Toast.makeText(MainActivity.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show();
					return;
				}
			
				searchType = 0;
			    routeOverlay = new RouteOverlay(MainActivity.this, mMapView);
			    // 此处仅展示一个方案作为示例
			    routeOverlay.setData(res.getPlan(0).getRoute(0));
			    //清除其他图层
			    mMapView.getOverlays().clear();
			    //添加路线图层
			    mMapView.getOverlays().add(routeOverlay);
			    //执行刷新使生效
			    mMapView.refresh();
			    // 使用zoomToSpan()绽放地图,使路线能完全显示在地图上
			    mMapView.getController().zoomToSpan(routeOverlay.getLatSpanE6(), routeOverlay.getLonSpanE6());
			    //移动地图到起点
			    mMapView.getController().animateTo(res.getStart().pt);
			    //将路线数据保存给全局变量
			    route = res.getPlan(0).getRoute(0);
			    //重置路线节点索引,节点浏览时使用
			    nodeIndex = -1;
			    mBtnPre.setVisibility(View.VISIBLE);
				mBtnNext.setVisibility(View.VISIBLE);
			}

			public void onGetTransitRouteResult(MKTransitRouteResult res,
					int error) {
				//起点或终点有歧义,需要选择具体的城市列表或地址列表
				if (error == MKEvent.ERROR_ROUTE_ADDR){
					//遍历所有地址
//					ArrayList stPois = res.getAddrResult().mStartPoiList;
//					ArrayList enPois = res.getAddrResult().mEndPoiList;
//					ArrayList stCities = res.getAddrResult().mStartCityList;
//					ArrayList enCities = res.getAddrResult().mEndCityList;
					return;
				}
				if (error != 0 || res == null) {
					Toast.makeText(MainActivity.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show();
					return;
				}
				
				searchType = 1;
				transitOverlay = new TransitOverlay (MainActivity.this, mMapView);
			    // 此处仅展示一个方案作为示例
			    transitOverlay.setData(res.getPlan(0));
			  //清除其他图层
			    mMapView.getOverlays().clear();
			  //添加路线图层
			    mMapView.getOverlays().add(transitOverlay);
			  //执行刷新使生效
			    mMapView.refresh();
			    // 使用zoomToSpan()绽放地图,使路线能完全显示在地图上
			    mMapView.getController().zoomToSpan(transitOverlay.getLatSpanE6(), transitOverlay.getLonSpanE6());
			  //移动地图到起点
			    mMapView.getController().animateTo(res.getStart().pt);
			  //重置路线节点索引,节点浏览时使用
			    nodeIndex = 0;
			    mBtnPre.setVisibility(View.VISIBLE);
				mBtnNext.setVisibility(View.VISIBLE);
			}

			public void onGetWalkingRouteResult(MKWalkingRouteResult res,
					int error) {
				//起点或终点有歧义,需要选择具体的城市列表或地址列表
				if (error == MKEvent.ERROR_ROUTE_ADDR){
					//遍历所有地址
//					ArrayList stPois = res.getAddrResult().mStartPoiList;
//					ArrayList enPois = res.getAddrResult().mEndPoiList;
//					ArrayList stCities = res.getAddrResult().mStartCityList;
//					ArrayList enCities = res.getAddrResult().mEndCityList;
					return;
				}
				if (error != 0 || res == null) {
					Toast.makeText(MainActivity.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show();
					return;
				}

				searchType = 2;
				routeOverlay = new RouteOverlay(MainActivity.this, mMapView);
			    // 此处仅展示一个方案作为示例
				routeOverlay.setData(res.getPlan(0).getRoute(0));
				//清除其他图层
			    mMapView.getOverlays().clear();
			  //添加路线图层
			    mMapView.getOverlays().add(routeOverlay);
			  //执行刷新使生效
			    mMapView.refresh();
			    // 使用zoomToSpan()绽放地图,使路线能完全显示在地图上
			    mMapView.getController().zoomToSpan(routeOverlay.getLatSpanE6(), routeOverlay.getLonSpanE6());
			  //移动地图到起点
			    mMapView.getController().animateTo(res.getStart().pt);
			    //将路线数据保存给全局变量
			    route = res.getPlan(0).getRoute(0);
			    //重置路线节点索引,节点浏览时使用
			    nodeIndex = -1;
			    mBtnPre.setVisibility(View.VISIBLE);
				mBtnNext.setVisibility(View.VISIBLE);
			    
			}
			public void onGetAddrResult(MKAddrInfo res, int error) {
				
				System.out.println("获取的信息是"+res.strAddr);
			}
			public void onGetPoiResult(MKPoiResult res, int arg1, int arg2) {
			}
			public void onGetBusDetailResult(MKBusLineResult result, int iError) {
			}

			@Override
			public void onGetSuggestionResult(MKSuggestionResult res, int arg1) {
			}

			@Override
			public void onGetPoiDetailSearchResult(int type, int iError) {
				// TODO Auto-generated method stub
			}

			@Override
			public void onGetShareUrlResult(MKShareUrlResult result, int type,
					int error) {
				// TODO Auto-generated method stub
				
			}
        });
	}
	/**
	 * 发起路线规划搜索示例
	 * @param v
	 */
	void SearchButtonProcess(View v) {
		//重置浏览节点的路线数据
		route = null;
		routeOverlay = null;
		transitOverlay = null; 
		mBtnPre.setVisibility(View.INVISIBLE);
		mBtnNext.setVisibility(View.INVISIBLE);
		// 处理搜索按钮响应
		EditText editSt = (EditText)findViewById(R.id.start);
		EditText editEn = (EditText)findViewById(R.id.end);
		
		
		
		double cLat=112.556305;
		double cLon=32.975724;
		
		double cLat2=112.560727;
		double cLon2=32.973437;
		
		
		//reverseGeocode(GeoPoint pt)
		
		// 对起点终点的name进行赋值,也可以直接对坐标赋值,赋值坐标则将根据坐标进行搜索
		MKPlanNode stNode = new MKPlanNode();
		//stNode.name = editSt.getText().toString();
		MKPlanNode enNode = new MKPlanNode();
		stNode.pt=new GeoPoint((int)(cLon * 1E6), (int)(cLat * 1E6));
		//enNode.name = editEn.getText().toString();
		enNode.pt=new GeoPoint((int)(cLon2 * 1E6), (int)(cLat2 * 1E6));

		 // stNode.pt = new GeoPoint((int) (31.205889 * 1E6), (int) (121.637942 * 1E6));  
		 // enNode.pt = new GeoPoint( (int) (31.243319 * 1E6), (int) (121.509075 * 1E6));  
		// 实际使用中请对起点终点城市进行正确的设定
		if (mBtnDrive.equals(v)) {
			mSearch.drivingSearch(null, stNode, null, enNode);
		} else if (mBtnTransit.equals(v)) {
			mSearch.transitSearch(null, stNode, enNode);
		} else if (mBtnWalk.equals(v)) {
			mSearch.walkingSearch(null, stNode, null, enNode);
			//mSearch.reverseGeocode(stNode.pt);
			//mSearch.reverseGeocode(enNode.pt);
		} 
	}
	/**
	 * 节点浏览示例
	 * @param v
	 */
	/*public void nodeClick(View v){
	//	viewCache = getLayoutInflater().inflate(R.layout.custom_text_view, null);
      //  popupText =(TextView) viewCache.findViewById(R.id.textcache);
		if (searchType == 0 || searchType == 2){
			//驾车、步行使用的数据结构相同,因此类型为驾车或步行,节点浏览方法相同
			if (nodeIndex < -1 || route == null || nodeIndex >= route.getNumSteps())
				return;
			
			//上一个节点
			if (mBtnPre.equals(v) && nodeIndex > 0){
				//索引减
				nodeIndex--;
				//移动到指定索引的坐标
				mMapView.getController().animateTo(route.getStep(nodeIndex).getPoint());
				//弹出泡泡
				popupText.setBackgroundResource(R.drawable.ic_launcher);
				popupText.setText(route.getStep(nodeIndex).getContent());
				pop.showPopup(BMapUtil.getBitmapFromView(popupText),
						route.getStep(nodeIndex).getPoint(),
						5);
			}
			//下一个节点
			if (mBtnNext.equals(v) && nodeIndex < (route.getNumSteps()-1)){
				//索引加
				nodeIndex++;
				//移动到指定索引的坐标
				mMapView.getController().animateTo(route.getStep(nodeIndex).getPoint());
				//弹出泡泡
				popupText.setBackgroundResource(R.drawable.ic_launcher);
				popupText.setText(route.getStep(nodeIndex).getContent());
				pop.showPopup(BMapUtil.getBitmapFromView(popupText),
						route.getStep(nodeIndex).getPoint(),
						5);
			}
		}
		if (searchType == 1){
			//公交换乘使用的数据结构与其他不同,因此单独处理节点浏览
			if (nodeIndex < -1 || transitOverlay == null || nodeIndex >= transitOverlay.getAllItem().size())
				return;
			
			//上一个节点
			if (mBtnPre.equals(v) && nodeIndex > 1){
				//索引减
				nodeIndex--;
				//移动到指定索引的坐标
				mMapView.getController().animateTo(transitOverlay.getItem(nodeIndex).getPoint());
				//弹出泡泡
				popupText.setBackgroundResource(R.drawable.ic_launcher);
				popupText.setText(transitOverlay.getItem(nodeIndex).getTitle());
				pop.showPopup(BMapUtil.getBitmapFromView(popupText),
						transitOverlay.getItem(nodeIndex).getPoint(),
						5);
			}
			//下一个节点
			if (mBtnNext.equals(v) && nodeIndex < (transitOverlay.getAllItem().size()-2)){
				//索引加
				nodeIndex++;
				//移动到指定索引的坐标
				mMapView.getController().animateTo(transitOverlay.getItem(nodeIndex).getPoint());
				//弹出泡泡
				popupText.setBackgroundResource(R.drawable.ic_launcher);
				popupText.setText(transitOverlay.getItem(nodeIndex).getTitle());
				pop.showPopup(BMapUtil.getBitmapFromView(popupText),
						transitOverlay.getItem(nodeIndex).getPoint(),
						5);
			}
		}
		
	}*/
	/**
	 * 创建弹出泡泡图层
	 */
	public void createPaopao(){
		
        //泡泡点击响应回调
        PopupClickListener popListener = new PopupClickListener(){
			@Override
			public void onClickedPopup(int index) {
				Log.v("click", "clickapoapo");
			}
        };
        pop = new PopupOverlay(mMapView,popListener);
	}

	/**
	 * 切换路线图标,刷新地图使其生效
	 * 注意: 起终点图标使用中心对齐.
	 */
	protected void changeRouteIcon() {
	    Button btn = (Button)findViewById(R.id.customicon);
	    if ( routeOverlay == null && transitOverlay == null){
	    	return ;
	    }
		if ( useDefaultIcon ){
	    	if ( routeOverlay != null){
	    	    routeOverlay.setStMarker(null);
	    	    routeOverlay.setEnMarker(null);
	        }
	        if ( transitOverlay != null){
	    	    transitOverlay.setStMarker(null);
	    	    transitOverlay.setEnMarker(null);
	        }
	        btn.setText("自定义起终点图标");
	        Toast.makeText(this, 
	        		       "将使用系统起终点图标", 
	        		       Toast.LENGTH_SHORT).show();
	    }
	    else{
		    if ( routeOverlay != null){
	    	  //  routeOverlay.setStMarker(getResources().getDrawable(R.drawable.icon_st));
	    	  //  routeOverlay.setEnMarker(getResources().getDrawable(R.drawable.icon_en));
	        }
	        if ( transitOverlay != null){
	    	  //  transitOverlay.setStMarker(getResources().getDrawable(R.drawable.icon_st));
	    	  //  transitOverlay.setEnMarker(getResources().getDrawable(R.drawable.icon_en));
	        }
	        btn.setText("系统起终点图标");
	        Toast.makeText(this, 
	        		       "将使用自定义起终点图标", 
	        		       Toast.LENGTH_SHORT).show();
	    }
	    useDefaultIcon = !useDefaultIcon;
	    mMapView.refresh();
		
	}

    @Override
    protected void onPause() {
        mMapView.onPause();
        super.onPause();
    }
    @Override
    protected void onResume() {
        mMapView.onResume();
        super.onResume();
    }
    @Override
    protected void onDestroy() {
        mMapView.destroy();
        mSearch.destory();
        super.onDestroy();
    }
	
    @Override
    protected void onSaveInstanceState(Bundle outState) {
    	super.onSaveInstanceState(outState);
    	mMapView.onSaveInstanceState(outState);
    	
    }
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
    	super.onRestoreInstanceState(savedInstanceState);
    	mMapView.onRestoreInstanceState(savedInstanceState);
    }
}

有问题可以提问。

drivingSearch

你可能感兴趣的:(编程代码,第三方API,编程技巧,android)