使用百度地图API实现驾车导航

做了一个利用百度地图API实现驾车导航的功能,不仅仅是驾车导航,利用这套API还可以实现公交以及步行的导航功能,这里只介绍如何实现驾车导航,步行和公交大同小异。首先来看看最后实现效果:

        


进入应用后首先显示蓝色点为当前位置,可以输入目的地来形成导航线路(图1),也可以点选地图上任意点来形成导航线路(图2,3),选定点后,在地图上会标注红色定位点,点击开始导航按钮后便会形成最佳驾车线路。


接下来看看实现步骤:

首先是工程结构

          

其中libs下面是申请百度开发者后到地图API下下载Android的地图支持包并导入工程,这里不再细说。

然后是布局文件:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <LinearLayout  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:orientation="horizontal" >  
  11.   
  12.         <TextView  
  13.             android:layout_width="wrap_content"  
  14.             android:layout_height="wrap_content"  
  15.             android:text="目的地:"  
  16.             android:textSize="17sp" />  
  17.   
  18.         <EditText  
  19.             android:id="@+id/et_destination"  
  20.             android:layout_width="fill_parent"  
  21.             android:hint="输入目的地名称或在地图上点选"  
  22.             android:textSize="14sp"  
  23.             android:layout_height="wrap_content" />  
  24.     </LinearLayout>  
  25.   
  26.     <LinearLayout  
  27.         android:layout_width="fill_parent"  
  28.         android:layout_height="wrap_content" >  
  29.   
  30.         <Button  
  31.             android:id="@+id/btn_navi"  
  32.             android:layout_width="fill_parent"  
  33.             android:layout_height="wrap_content"  
  34.             android:layout_weight="1"  
  35.             android:text="开始导航" />  
  36.   
  37.         <Button  
  38.             android:id="@+id/btn_clear"  
  39.             android:layout_width="fill_parent"  
  40.             android:layout_height="wrap_content"  
  41.             android:layout_weight="1"  
  42.             android:text="清除路线" />  
  43.     </LinearLayout>  
  44.   
  45.     <com.baidu.mapapi.MapView  
  46.         android:id="@+id/bmapsView"  
  47.         android:layout_width="fill_parent"  
  48.         android:layout_height="fill_parent"  
  49.         android:clickable="true" />  
  50.   
  51. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="目的地:"
            android:textSize="17sp" />

        <EditText
            android:id="@+id/et_destination"
            android:layout_width="fill_parent"
            android:hint="输入目的地名称或在地图上点选"
            android:textSize="14sp"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/btn_navi"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="开始导航" />

        <Button
            android:id="@+id/btn_clear"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="清除路线" />
    </LinearLayout>

    <com.baidu.mapapi.MapView
        android:id="@+id/bmapsView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="true" />

</LinearLayout>

然后是实现自定义的地图图层MyItemizedOverlay.java,这个类的作用是实现可点击地图图层的作用,点击地图后,便可以显示当前位置的经纬度,并可设置为目的地。

  1. /** 
  2.  * 自定义图层 
  3.  * @author Ryan 
  4.  */  
  5. public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {  
  6.       
  7.     private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();      
  8.     private Context context;  
  9.       
  10.     public MyItemizedOverlay(Context context,Drawable drawale) {  
  11.         super(boundCenterBottom(drawale));        
  12.         this.context=context;  
  13.     }  
  14.       
  15.     @Override  
  16.     protected OverlayItem createItem(int i) {  
  17.         return mOverlays.get(i);  
  18.     }  
  19.       
  20.     @Override  
  21.     public int size() {  
  22.         return mOverlays.size();  
  23.     }  
  24.       
  25.     // 点击地图标注显示的内容   
  26.     @Override  
  27.     protected boolean onTap(int index) {  
  28.         //这个方法的重写弹出信息等   
  29.         return true;  
  30.     }  
  31.       
  32.     @Override  
  33.     public void draw(Canvas canvas, MapView mapView, boolean shadow) {  
  34.         super.draw(canvas, mapView, shadow);  
  35.     }  
  36.       
  37.     // Define a method in order to add new OverlayItems to our ArrayList   
  38.     public void addOverlay(OverlayItem overlay) {  
  39.         // add OverlayItems   
  40.         mOverlays.add(overlay);  
  41.         populate();  
  42.     }  
  43.       
  44.     //该方法的重写可以相应点击图标的区域内还是外   
  45.     @Override  
  46.     public boolean onTap(GeoPoint p, MapView mapView) {  
  47.         final SharedPreferences sharedPreferences = context.getSharedPreferences("navigation_pre", Context.MODE_WORLD_WRITEABLE);  
  48.           
  49.         //p获取的经纬度数据是整型变量,需要转换为float类型   
  50.         final float lat=p.getLatitudeE6();  
  51.         final float lon=p.getLongitudeE6();  
  52.         final MapView map = mapView;  
  53.           
  54.         float latitude = sharedPreferences.getFloat("lat"0);  
  55.         if (latitude == 0) {  
  56.             AlertDialog.Builder builder = new AlertDialog.Builder(this.context);  
  57.             builder.setTitle("设置目的地");  
  58.             builder.setMessage("设置选中的点为目的地吗?");  
  59.             builder.setPositiveButton("确定",new OnClickListener() {  
  60.                   
  61.                 @Override  
  62.                 public void onClick(DialogInterface dialog, int which) {  
  63.                     List<Overlay> overlays = map.getOverlays();  
  64.                     GeoPoint gpoint = new GeoPoint((int)lat,(int)lon);  
  65.                     OverlayItem overlayitem = new OverlayItem(gpoint, "title""content");  
  66.                     Drawable drawale = context.getResources().getDrawable(R.drawable.current_mark);  
  67.                     MyItemizedOverlay iconOverlay = new MyItemizedOverlay(context,drawale);  
  68.                     // 添加图层   
  69.                     iconOverlay.addOverlay(overlayitem);  
  70.                     overlays.add(iconOverlay);  
  71.                     map.getController().animateTo(gpoint);  
  72.                       
  73.                     Editor editor = sharedPreferences.edit();  
  74.                     editor.putFloat("lat", lat);  
  75.                     editor.putFloat("lon", lon);  
  76.                     editor.commit();  
  77.                     Toast.makeText(context, "纬度:"+lat / 1E6+"\n经度:"+lon / 1E6, Toast.LENGTH_SHORT).show();    
  78.                 }  
  79.             });  
  80.             builder.setNegativeButton("取消"null);  
  81.             builder.create().show();  
  82.         }else {  
  83. //          AlertDialog.Builder builder = new AlertDialog.Builder(this.context);   
  84. //          builder.setTitle("设置目的地");   
  85. //          builder.setMessage("已经设置过线路,请先点击清除路线按钮清除当前路线");   
  86. //          builder.setNegativeButton("确定", null);   
  87. //          builder.create().show();   
  88.             Toast.makeText(context, "已经设置过线路,请先点击清除路线按钮清除当前路线",Toast.LENGTH_SHORT).show();    
  89.               
  90.         }  
  91.           
  92.         return super.onTap(p, mapView);  
  93.     }     
  94. }  
/**
 * 自定义图层
 * @author Ryan
 */
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {
	
	private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();	
	private Context context;
	
	public MyItemizedOverlay(Context context,Drawable drawale) {
		super(boundCenterBottom(drawale));		
		this.context=context;
	}
	
	@Override
	protected OverlayItem createItem(int i) {
		return mOverlays.get(i);
	}
	
	@Override
	public int size() {
		return mOverlays.size();
	}
	
	// 点击地图标注显示的内容
	@Override
	protected boolean onTap(int index) {
		//这个方法的重写弹出信息等
		return true;
	}
	
	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		super.draw(canvas, mapView, shadow);
	}
	
	// Define a method in order to add new OverlayItems to our ArrayList
	public void addOverlay(OverlayItem overlay) {
		// add OverlayItems
		mOverlays.add(overlay);
		populate();
	}
	
	//该方法的重写可以相应点击图标的区域内还是外
	@Override
	public boolean onTap(GeoPoint p, MapView mapView) {
		final SharedPreferences sharedPreferences = context.getSharedPreferences("navigation_pre", Context.MODE_WORLD_WRITEABLE);
		
		//p获取的经纬度数据是整型变量,需要转换为float类型
		final float lat=p.getLatitudeE6();
		final float lon=p.getLongitudeE6();
		final MapView map = mapView;
		
		float latitude = sharedPreferences.getFloat("lat", 0);
		if (latitude == 0) {
			AlertDialog.Builder builder = new AlertDialog.Builder(this.context);
			builder.setTitle("设置目的地");
			builder.setMessage("设置选中的点为目的地吗?");
			builder.setPositiveButton("确定",new OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					List<Overlay> overlays = map.getOverlays();
					GeoPoint gpoint = new GeoPoint((int)lat,(int)lon);
					OverlayItem overlayitem = new OverlayItem(gpoint, "title", "content");
					Drawable drawale = context.getResources().getDrawable(R.drawable.current_mark);
					MyItemizedOverlay iconOverlay = new MyItemizedOverlay(context,drawale);
					// 添加图层
					iconOverlay.addOverlay(overlayitem);
					overlays.add(iconOverlay);
					map.getController().animateTo(gpoint);
					
					Editor editor = sharedPreferences.edit();
					editor.putFloat("lat", lat);
					editor.putFloat("lon", lon);
					editor.commit();
					Toast.makeText(context, "纬度:"+lat / 1E6+"\n经度:"+lon / 1E6, Toast.LENGTH_SHORT).show();	
				}
			});
			builder.setNegativeButton("取消", null);
			builder.create().show();
		}else {
//			AlertDialog.Builder builder = new AlertDialog.Builder(this.context);
//			builder.setTitle("设置目的地");
//			builder.setMessage("已经设置过线路,请先点击清除路线按钮清除当前路线");
//			builder.setNegativeButton("确定", null);
//			builder.create().show();
			Toast.makeText(context, "已经设置过线路,请先点击清除路线按钮清除当前路线",Toast.LENGTH_SHORT).show();	
			
		}
		
		return super.onTap(p, mapView);
	}	
}

最后是主Activity实现类,注释中有详细说明:

  1. public class NavigationDemoActivity extends MapActivity {  
  2.     //Map key   
  3.     private String mMapKey = "你的MapKey,到百度开发者官网申请";  
  4.       
  5.     private EditText destinationEditText = null;  
  6.     private Button startNaviButton = null;  
  7.     private Button clearButton = null;  
  8.     private MapView mapView = null;  
  9.     private BMapManager mMapManager = null;  
  10.     private MyLocationOverlay myLocationOverlay = null;  
  11.     //onResume时注册此listener,onPause时需要Remove,注意此listener不是Android自带的,是百度API中的   
  12.     private LocationListener locationListener = null;  
  13.     //搜索模块   
  14.     private MKSearch searchModel = null;  
  15.     private GeoPoint pt = null;  
  16.     private SharedPreferences sharedPreferences;  
  17.       
  18.     @Override  
  19.     public void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  22.         setContentView(R.layout.main);  
  23.         //弹出使用说明对话框   
  24.         showIntroduceDialog();  
  25.           
  26.         sharedPreferences = this.getSharedPreferences("navigation_pre", Context.MODE_WORLD_WRITEABLE);  
  27.         destinationEditText = (EditText) this.findViewById(R.id.et_destination);  
  28.         startNaviButton = (Button) this.findViewById(R.id.btn_navi);  
  29.         clearButton = (Button) this.findViewById(R.id.btn_clear);  
  30.           
  31.         //初始化地图管理器   
  32.         mMapManager = new BMapManager(getApplication());  
  33.         mMapManager.init(mMapKey, new MyGeneralListener());  
  34.         super.initMapActivity(mMapManager);  
  35.           
  36.         mapView = (MapView) this.findViewById(R.id.bmapsView);  
  37.         //设置启用内置的缩放控件   
  38.         mapView.setBuiltInZoomControls(true);    
  39.         //设置在缩放动画过程中也显示overlay,默认为不绘制   
  40. //        mapView.setDrawOverlayWhenZooming(true);   
  41.         //设置初始化地图的缩放级别   
  42.         mapView.getController().setZoom(16);  
  43.         mapView.setClickable(true);  
  44.           
  45.         //获取当前位置层   
  46.         myLocationOverlay = new MyLocationOverlay(this, mapView);  
  47.         //将当前位置的层添加到地图底层中   
  48.         mapView.getOverlays().add(myLocationOverlay);  
  49.           
  50.         //添加可点选地图获取目的地的层   
  51.         addTapOverLay();  
  52.           
  53.         //注册定位事件   
  54.         locationListener = new LocationListener(){  
  55.   
  56.             @Override  
  57.             public void onLocationChanged(Location location) {  
  58.                 if (location != null){  
  59.                     //生成GEO类型坐标并在地图上定位到该坐标标示的地点   
  60.                      pt = new GeoPoint((int)(location.getLatitude() * 1e6),  
  61.                             (int)(location.getLongitude() * 1e6));  
  62.                      mapView.getController().animateTo(pt);  
  63.                 }  
  64.             }  
  65.         };  
  66.           
  67.         //初始化搜索模块   
  68.         searchModel = new MKSearch();  
  69.         //设置路线策略为最短距离   
  70.         searchModel.setDrivingPolicy(MKSearch.ECAR_DIS_FIRST);  
  71.         searchModel.init(mMapManager, new MKSearchListener() {  
  72.             //获取驾车路线回调方法   
  73.             @Override  
  74.             public void onGetDrivingRouteResult(MKDrivingRouteResult res, int error) {  
  75.                 // 错误号可参考MKEvent中的定义   
  76.                 if (error != 0 || res == null) {  
  77.                     Toast.makeText(NavigationDemoActivity.this"抱歉,未找到结果", Toast.LENGTH_SHORT).show();  
  78.                     return;  
  79.                 }  
  80.                 RouteOverlay routeOverlay = new RouteOverlay(NavigationDemoActivity.this, mapView);  
  81.                   
  82.                 // 此处仅展示一个方案作为示例   
  83.                 MKRoute route = res.getPlan(0).getRoute(0);  
  84.                 int distanceM = route.getDistance();  
  85.                 String distanceKm = String.valueOf(distanceM / 1000) +"."+String.valueOf(distanceM % 1000);  
  86.                 System.out.println("距离:"+distanceKm+"公里---节点数量:"+route.getNumSteps());  
  87.                 for (int i = 0; i < route.getNumSteps(); i++) {  
  88.                     MKStep step = route.getStep(i);  
  89.                     System.out.println("节点信息:"+step.getContent());  
  90.                     System.out.println("经度:"+step.getPoint().getLongitudeE6() / 1E6 +" 纬度:"+step.getPoint().getLatitudeE6() / 1E6);  
  91.                 }  
  92.                 routeOverlay.setData(route);  
  93.                 mapView.getOverlays().clear();  
  94.                 mapView.getOverlays().add(routeOverlay);  
  95.                 mapView.invalidate();  
  96.                 mapView.getController().animateTo(res.getStart().pt);  
  97.             }  
  98.               
  99.             //以下两种方式和上面的驾车方案实现方法一样   
  100.             @Override  
  101.             public void onGetWalkingRouteResult(MKWalkingRouteResult res, int error) {  
  102.                 //获取步行路线   
  103.             }  
  104.               
  105.             @Override  
  106.             public void onGetTransitRouteResult(MKTransitRouteResult arg0, int arg1) {  
  107.                 //获取公交线路   
  108.             }  
  109.               
  110.             @Override  
  111.             public void onGetBusDetailResult(MKBusLineResult arg0, int arg1) {  
  112.             }  
  113.             @Override  
  114.             public void onGetAddrResult(MKAddrInfo arg0, int arg1) {  
  115.             }  
  116.             @Override  
  117.             public void onGetSuggestionResult(MKSuggestionResult arg0, int arg1) {  
  118.             }  
  119.             @Override  
  120.             public void onGetPoiResult(MKPoiResult arg0, int arg1, int arg2) {  
  121.             }  
  122.         });  
  123.           
  124.         startNaviButton.setOnClickListener(new OnClickListener() {  
  125.               
  126.             @Override  
  127.             public void onClick(View v) {  
  128.                 String destination = destinationEditText.getText().toString();  
  129.                   
  130.                 //设置起始地(当前位置)   
  131.                 MKPlanNode startNode = new MKPlanNode();  
  132.                 startNode.pt = pt;  
  133.                   
  134.                 //设置目的地   
  135.                 MKPlanNode endNode = new MKPlanNode();   
  136.                   
  137.                 float lat = sharedPreferences.getFloat("lat"0);  
  138.                 float lon = sharedPreferences.getFloat("lon"0);  
  139.                   
  140.                 if (lat != 0 && lon != 0) {  
  141.                     endNode.pt = new GeoPoint((int)lat,(int)lon);  
  142.                 }else if (!destination.equals("")) {  
  143.                     endNode.name = destination;  
  144.                 }else {  
  145.                     Toast.makeText(NavigationDemoActivity.this"请输入或点选目的地",Toast.LENGTH_SHORT).show();  
  146.                     return;  
  147.                 }  
  148.                   
  149.                 //展开搜索的城市   
  150.                 String city = getResources().getString(R.string.beijing);  
  151.                 searchModel.drivingSearch(city, startNode, city, endNode);  
  152.                   
  153.                 //步行路线   
  154. //              searchModel.walkingSearch(city, startNode, city, endNode);   
  155.                 //公交路线   
  156. //              searchModel.transitSearch(city, startNode, endNode);   
  157.             }  
  158.         });  
  159.           
  160.         //清除路线按钮事件   
  161.         clearButton.setOnClickListener(new OnClickListener() {  
  162.               
  163.             @Override  
  164.             public void onClick(View v) {  
  165.                 List<Overlay> overlays = mapView.getOverlays();  
  166.                   
  167.                 if (sharedPreferences.getFloat("lon"0) != 0) {  
  168.                     //移除顶层的路线图层   
  169.                     overlays.remove(overlays.size() - 1);  
  170.                     //添加用户当前位置图层   
  171.                     overlays.add(myLocationOverlay);  
  172.                     //地图更新定位到当前位置   
  173.                     mapView.getController().animateTo(pt);  
  174.                       
  175.                     //清除存储的经纬度信息   
  176.                     Editor editor = sharedPreferences.edit();  
  177.                     editor.clear();  
  178.                     editor.commit();  
  179.                       
  180.                     //添加可点选图层   
  181.                     addTapOverLay();  
  182.                       
  183.                 }else if (!destinationEditText.getText().toString().equals("")) {  
  184.                     overlays.remove(overlays.size() - 1);  
  185.                     overlays.add(myLocationOverlay);  
  186.                     mapView.getController().animateTo(pt);  
  187.                     addTapOverLay();  
  188.                 }else {  
  189.                     Toast.makeText(NavigationDemoActivity.this"没有设置路线", Toast.LENGTH_SHORT).show();  
  190.                 }  
  191.             }  
  192.         });  
  193.     }  
  194.       
  195.     public void showIntroduceDialog(){  
  196.         AlertDialog.Builder builder = new AlertDialog.Builder(this);  
  197.         builder.setTitle("使用说明");  
  198.         StringBuilder sb = new StringBuilder();  
  199.         sb.append("1.地图中蓝色点为当前位置;\n\n");  
  200.         sb.append("2.双指捏合或点击缩放按钮可以缩放地图;\n\n");  
  201.         sb.append("3.在输入框中输入目的地或在地图上点选目的地;\n\n");  
  202.         sb.append("4.选取目的地后点击按钮开始导航;\n\n");  
  203.         sb.append("5.点击清除按钮取消本次导航路线;");  
  204.         builder.setMessage(sb.toString());  
  205.         builder.setNegativeButton("确定"null);  
  206.         builder.create().show();  
  207.     }  
  208.       
  209.     public void addTapOverLay(){  
  210.         //以一副透明图片标示可点选图层,这里在地图上不显示出来,只提供可点选目的地功能   
  211.         GeoPoint gpoint = new GeoPoint((int) (39.914714 * 1E6), (int) (116.404269 * 1E6));  
  212.         OverlayItem overlayitem = new OverlayItem(gpoint, "title""content");  
  213.         Drawable drawale = getResources().getDrawable(R.drawable.current);  
  214.         MyItemizedOverlay iconOverlay = new MyItemizedOverlay(NavigationDemoActivity.this,drawale);  
  215.         // 添加图层   
  216.         iconOverlay.addOverlay(overlayitem);  
  217.         mapView.getOverlays().add(iconOverlay);  
  218.     }  
  219.       
  220.     @Override  
  221.     protected void onResume() {  
  222.         mMapManager.getLocationManager().requestLocationUpdates(locationListener);  
  223.         myLocationOverlay.enableMyLocation();  
  224.         myLocationOverlay.enableCompass(); // 打开指南针   
  225.         mMapManager.start();  
  226.           
  227.         super.onResume();  
  228.     }  
  229.       
  230.     @Override  
  231.     protected void onPause() {  
  232.         mMapManager.getLocationManager().removeUpdates(locationListener);  
  233.         myLocationOverlay.disableMyLocation();//显示当前位置   
  234.         myLocationOverlay.disableCompass(); // 关闭指南针   
  235.         mMapManager.stop();  
  236.         super.onPause();  
  237.     }  
  238.   
  239.     @Override  
  240.     protected boolean isRouteDisplayed() {  
  241.         // TODO Auto-generated method stub   
  242.         return false;  
  243.     }  
  244.       
  245.     //按物理返回键退出应用时清空存储的经纬度信息   
  246.     @Override  
  247.     public boolean dispatchKeyEvent(KeyEvent event) {  
  248.         if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {  
  249.             Editor editor = sharedPreferences.edit();  
  250.             editor.clear();  
  251.             editor.commit();  
  252.         }  
  253.         return super.dispatchKeyEvent(event);  
  254.     }  
  255.       
  256.     // 常用事件监听,用来处理通常的网络错误,授权验证错误等   
  257.     class MyGeneralListener implements MKGeneralListener {  
  258.             @Override  
  259.             public void onGetNetworkState(int iError) {  
  260.                 Log.d("MyGeneralListener""onGetNetworkState error is "+ iError);  
  261.                 Toast.makeText(NavigationDemoActivity.this"您的网络出错啦!",  
  262.                         Toast.LENGTH_LONG).show();  
  263.             }  
  264.   
  265.             @Override  
  266.             public void onGetPermissionState(int iError) {  
  267.                 Log.d("MyGeneralListener""onGetPermissionState error is "+ iError);  
  268.                 if (iError ==  MKEvent.ERROR_PERMISSION_DENIED) {  
  269.                     // 授权Key错误:   
  270.                     Toast.makeText(NavigationDemoActivity.this,   
  271.                             "请在BMapApiDemoApp.java文件输入正确的授权Key!",  
  272.                             Toast.LENGTH_LONG).show();  
  273.                 }  
  274.             }  
  275.         }  
  276. }  
public class NavigationDemoActivity extends MapActivity {
	//Map key
	private String mMapKey = "你的MapKey,到百度开发者官网申请";
	
	private EditText destinationEditText = null;
	private Button startNaviButton = null;
	private Button clearButton = null;
	private MapView mapView = null;
	private BMapManager mMapManager = null;
	private MyLocationOverlay myLocationOverlay = null;
	//onResume时注册此listener,onPause时需要Remove,注意此listener不是Android自带的,是百度API中的
	private LocationListener locationListener = null;
	//搜索模块
	private MKSearch searchModel = null;
	private GeoPoint pt = null;
	private SharedPreferences sharedPreferences;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);
        //弹出使用说明对话框
        showIntroduceDialog();
        
        sharedPreferences = this.getSharedPreferences("navigation_pre", Context.MODE_WORLD_WRITEABLE);
        destinationEditText = (EditText) this.findViewById(R.id.et_destination);
        startNaviButton = (Button) this.findViewById(R.id.btn_navi);
        clearButton = (Button) this.findViewById(R.id.btn_clear);
        
        //初始化地图管理器
        mMapManager = new BMapManager(getApplication());
        mMapManager.init(mMapKey, new MyGeneralListener());
        super.initMapActivity(mMapManager);
        
        mapView = (MapView) this.findViewById(R.id.bmapsView);
        //设置启用内置的缩放控件
        mapView.setBuiltInZoomControls(true);  
        //设置在缩放动画过程中也显示overlay,默认为不绘制
//        mapView.setDrawOverlayWhenZooming(true);
        //设置初始化地图的缩放级别
        mapView.getController().setZoom(16);
        mapView.setClickable(true);
        
        //获取当前位置层
        myLocationOverlay = new MyLocationOverlay(this, mapView);
        //将当前位置的层添加到地图底层中
        mapView.getOverlays().add(myLocationOverlay);
        
        //添加可点选地图获取目的地的层
        addTapOverLay();
        
        //注册定位事件
        locationListener = new LocationListener(){

			@Override
			public void onLocationChanged(Location location) {
				if (location != null){
					//生成GEO类型坐标并在地图上定位到该坐标标示的地点
					 pt = new GeoPoint((int)(location.getLatitude() * 1e6),
							(int)(location.getLongitude() * 1e6));
					 mapView.getController().animateTo(pt);
				}
			}
        };
        
        //初始化搜索模块
        searchModel = new MKSearch();
        //设置路线策略为最短距离
        searchModel.setDrivingPolicy(MKSearch.ECAR_DIS_FIRST);
        searchModel.init(mMapManager, new MKSearchListener() {
			//获取驾车路线回调方法
			@Override
			public void onGetDrivingRouteResult(MKDrivingRouteResult res, int error) {
				// 错误号可参考MKEvent中的定义
				if (error != 0 || res == null) {
					Toast.makeText(NavigationDemoActivity.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show();
					return;
				}
				RouteOverlay routeOverlay = new RouteOverlay(NavigationDemoActivity.this, mapView);
				
			    // 此处仅展示一个方案作为示例
				MKRoute route = res.getPlan(0).getRoute(0);
				int distanceM = route.getDistance();
				String distanceKm = String.valueOf(distanceM / 1000) +"."+String.valueOf(distanceM % 1000);
				System.out.println("距离:"+distanceKm+"公里---节点数量:"+route.getNumSteps());
				for (int i = 0; i < route.getNumSteps(); i++) {
					MKStep step = route.getStep(i);
					System.out.println("节点信息:"+step.getContent());
					System.out.println("经度:"+step.getPoint().getLongitudeE6() / 1E6 +" 纬度:"+step.getPoint().getLatitudeE6() / 1E6);
				}
			    routeOverlay.setData(route);
			    mapView.getOverlays().clear();
			    mapView.getOverlays().add(routeOverlay);
			    mapView.invalidate();
			    mapView.getController().animateTo(res.getStart().pt);
			}
			
			//以下两种方式和上面的驾车方案实现方法一样
			@Override
			public void onGetWalkingRouteResult(MKWalkingRouteResult res, int error) {
				//获取步行路线
			}
			
			@Override
			public void onGetTransitRouteResult(MKTransitRouteResult arg0, int arg1) {
				//获取公交线路
			}
			
			@Override
			public void onGetBusDetailResult(MKBusLineResult arg0, int arg1) {
			}
			@Override
			public void onGetAddrResult(MKAddrInfo arg0, int arg1) {
			}
			@Override
			public void onGetSuggestionResult(MKSuggestionResult arg0, int arg1) {
			}
			@Override
			public void onGetPoiResult(MKPoiResult arg0, int arg1, int arg2) {
			}
		});
        
        startNaviButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				String destination = destinationEditText.getText().toString();
				
				//设置起始地(当前位置)
				MKPlanNode startNode = new MKPlanNode();
				startNode.pt = pt;
				
				//设置目的地
				MKPlanNode endNode = new MKPlanNode(); 
				
				float lat = sharedPreferences.getFloat("lat", 0);
				float lon = sharedPreferences.getFloat("lon", 0);
				
				if (lat != 0 && lon != 0) {
					endNode.pt = new GeoPoint((int)lat,(int)lon);
				}else if (!destination.equals("")) {
					endNode.name = destination;
				}else {
					Toast.makeText(NavigationDemoActivity.this, "请输入或点选目的地",Toast.LENGTH_SHORT).show();
					return;
				}
				
				//展开搜索的城市
				String city = getResources().getString(R.string.beijing);
				searchModel.drivingSearch(city, startNode, city, endNode);
				
				//步行路线
//				searchModel.walkingSearch(city, startNode, city, endNode);
				//公交路线
//				searchModel.transitSearch(city, startNode, endNode);
			}
		});
        
        //清除路线按钮事件
        clearButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				List<Overlay> overlays = mapView.getOverlays();
				
				if (sharedPreferences.getFloat("lon", 0) != 0) {
					//移除顶层的路线图层
					overlays.remove(overlays.size() - 1);
					//添加用户当前位置图层
					overlays.add(myLocationOverlay);
					//地图更新定位到当前位置
					mapView.getController().animateTo(pt);
					
					//清除存储的经纬度信息
					Editor editor = sharedPreferences.edit();
					editor.clear();
					editor.commit();
					
					//添加可点选图层
					addTapOverLay();
					
				}else if (!destinationEditText.getText().toString().equals("")) {
					overlays.remove(overlays.size() - 1);
					overlays.add(myLocationOverlay);
					mapView.getController().animateTo(pt);
					addTapOverLay();
				}else {
					Toast.makeText(NavigationDemoActivity.this, "没有设置路线", Toast.LENGTH_SHORT).show();
				}
			}
		});
    }
    
    public void showIntroduceDialog(){
    	AlertDialog.Builder builder = new AlertDialog.Builder(this);
    	builder.setTitle("使用说明");
    	StringBuilder sb = new StringBuilder();
    	sb.append("1.地图中蓝色点为当前位置;\n\n");
    	sb.append("2.双指捏合或点击缩放按钮可以缩放地图;\n\n");
    	sb.append("3.在输入框中输入目的地或在地图上点选目的地;\n\n");
    	sb.append("4.选取目的地后点击按钮开始导航;\n\n");
    	sb.append("5.点击清除按钮取消本次导航路线;");
    	builder.setMessage(sb.toString());
    	builder.setNegativeButton("确定", null);
    	builder.create().show();
    }
    
    public void addTapOverLay(){
    	//以一副透明图片标示可点选图层,这里在地图上不显示出来,只提供可点选目的地功能
    	GeoPoint gpoint = new GeoPoint((int) (39.914714 * 1E6),	(int) (116.404269 * 1E6));
		OverlayItem overlayitem = new OverlayItem(gpoint, "title", "content");
		Drawable drawale = getResources().getDrawable(R.drawable.current);
		MyItemizedOverlay iconOverlay = new MyItemizedOverlay(NavigationDemoActivity.this,drawale);
		// 添加图层
		iconOverlay.addOverlay(overlayitem);
		mapView.getOverlays().add(iconOverlay);
    }
    
    @Override
	protected void onResume() {
		mMapManager.getLocationManager().requestLocationUpdates(locationListener);
        myLocationOverlay.enableMyLocation();
        myLocationOverlay.enableCompass(); // 打开指南针
		mMapManager.start();
		
		super.onResume();
	}
    
    @Override
	protected void onPause() {
		mMapManager.getLocationManager().removeUpdates(locationListener);
		myLocationOverlay.disableMyLocation();//显示当前位置
		myLocationOverlay.disableCompass(); // 关闭指南针
		mMapManager.stop();
		super.onPause();
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
	//按物理返回键退出应用时清空存储的经纬度信息
	@Override
	public boolean dispatchKeyEvent(KeyEvent event) {
		if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
			Editor editor = sharedPreferences.edit();
			editor.clear();
			editor.commit();
		}
		return super.dispatchKeyEvent(event);
	}
	
	// 常用事件监听,用来处理通常的网络错误,授权验证错误等
	class MyGeneralListener implements MKGeneralListener {
			@Override
			public void onGetNetworkState(int iError) {
				Log.d("MyGeneralListener", "onGetNetworkState error is "+ iError);
				Toast.makeText(NavigationDemoActivity.this, "您的网络出错啦!",
						Toast.LENGTH_LONG).show();
			}

			@Override
			public void onGetPermissionState(int iError) {
				Log.d("MyGeneralListener", "onGetPermissionState error is "+ iError);
				if (iError ==  MKEvent.ERROR_PERMISSION_DENIED) {
					// 授权Key错误:
					Toast.makeText(NavigationDemoActivity.this, 
							"请在BMapApiDemoApp.java文件输入正确的授权Key!",
							Toast.LENGTH_LONG).show();
				}
			}
		}
}

最后是配置文件:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.ericssonlabs"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk android:minSdkVersion="8" />  
  8.   
  9.     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>  
  10.     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>  
  11.     <uses-permission android:name="android.permission.INTERNET"></uses-permission>  
  12.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>  
  13.     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>    
  14.     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>   
  15.     <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>  
  16.       
  17.     <supports-screens android:largeScreens="true"  
  18.         android:normalScreens="true" android:smallScreens="true"  
  19.         android:resizeable="true" android:anyDensity="true"/>  
  20.     <uses-sdk android:minSdkVersion="3"></uses-sdk>  
  21.   
  22.     <application  
  23.         android:icon="@drawable/ic_launcher"  
  24.         android:label="@string/app_name" >  
  25.         <activity  
  26.             android:name=".NavigationDemoActivity"  
  27.             android:label="@string/app_name" >  
  28.             <intent-filter>  
  29.                 <action android:name="android.intent.action.MAIN" />  
  30.   
  31.                 <category android:name="android.intent.category.LAUNCHER" />  
  32.             </intent-filter>  
  33.         </activity>  
  34.     </application>  
  35.   
  36. </manifest>  
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ericssonlabs"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
	<uses-permission android:name="android.permission.INTERNET"></uses-permission>
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>  
	<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> 
	<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
	
	<supports-screens android:largeScreens="true"
	    android:normalScreens="true" android:smallScreens="true"
	    android:resizeable="true" android:anyDensity="true"/>
	<uses-sdk android:minSdkVersion="3"></uses-sdk>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".NavigationDemoActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值