本文主要内容包括:如何根据百度地图接口实现定位,并实现从A到B的路径规划功能(驾车,公交,步行)。本文主要提供给新手参考,如果有错误希望博友们指出以便及时改正。
1.申请百度地图SDK的密钥(填写安全码是一定注意:Android SDK安全码组成:数字签名+;+包名)。
2.在 http://lbsyun.baidu.com/sdk/download 下载示例代码。
3.Eclipse中导入实例代码。
4.在AndroidManifest.xml中 把申请的密钥填进去(如图).
5.这样就可以运行我们刚刚下载的百度地图demo.
我们下面要做的就是把demo里面能用的代码改成我们需要的功能:
我们需要的功能就是:获取我的位置,然后帮我导航到我想去的地方。(实际开发中可能是与服务器交互的任意位置)
首先贴上我们的项目结构,文章结尾也会有代码下载地址(免积分下载)。
1.我们需要下载百度地图API的示例代码与类参考。如下图所示。
2.Eclipse导入百度地图\BaiduLBS_AndroidSDK_Sample\地图+检索+LBS云检索+工具 下的示例项目,大家可以按照本文开头的配置运行一下demo,本文就不在展示demo运行效果。
3.由于我们这次需要的功能是线路规划,所以demo中我们需要的类是 RoutePlanDemo,二话不说新建项目先将这个Activity类粘贴进去。
4.我们需要在我们自己的Application类中初始化百度SDK组件,所以我们再把demo中的 DemoApplication类粘贴到新建项目。而且我们需要在AndroidManifest中配置此类。配置文件如下。
<span style="font-family:Times New Roman;"><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.mybaidumap" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> <application android:name="com.mybaidu.DemoApplication" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="hOR6hNauVspidl4M3OmQttfm" /> <activity android:name="com.mybaidu.RoutePlanDemo" android:configChanges="orientation|keyboardHidden" android:screenOrientation="portrait" android:label="BaiduMapSDKDemo" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" > </service> </application> <permission android:name="android.permission.BAIDU_LOCATION_SERVICE" > </permission> <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" > </uses-permission> <uses-permission android:name="android.permission.INTERNET" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" > </uses-permission> <!-- <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"></uses-permission> --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" > </uses-permission> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name="android.permission.WAKE_LOCK" > </uses-permission> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_GPS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" /> <!-- SDK1.5需要android.permission.GET_TASKS权限判断本程序是否为当前运行的应用? --> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.CAMERA" > </uses-permission> <uses-permission android:name="android.permission.RECORD_AUDIO" > </uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" > </uses-permission> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!-- 来电消音 --> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" > </uses-permission> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="false" android:resizeable="true" android:smallScreens="true" /> </manifest></span>
5.现在我们来解读我们刚刚粘贴过来的 RoutePlanDemo类,百度的注释已经很详细了,根据运行demo后的效果,我们只要发现哪里传入地址参数就可以。下面两句就是我们需要传入的地图参数。
PlanNode stNode = PlanNode.withCityNameAndPlaceName("北京", editSt.getText().toString()); PlanNode enNode = PlanNode.withCityNameAndPlaceName("北京", editEn.getText().toString());
6.可以看出demo中将两个位置参数赋值给了PlanNode对象, 现在我们打开刚刚我们下载的类参考中的文档,路径如下:百度地图\BaiduLBS_AndroidSDK_Docs\地图+检索+LBS云检索+工具\index.html找到PlanNode类,此类提供给我们两个方法如下图所示:
7.所以我们只需要把我们的起点和终点的位置信息(经纬度或者地名和城市名)放入方法的参数中即可.而现在我们需要的起点是根据我们实时的定位而决定的,所以现在我们还需要调用百度的定位方法,来获取我们的当前定位信息。
8.要想获取我们当前所在位置,我们可以实现BDLocationListener接口,使用BDLocation类中的
getLatitude()与getLongitude方法,获取我们当前的位置。然后将获取到的经纬度放到下面的方法中即可。
PlanNode stNode = PlanNode.withLocation(new LatLng(myLatitude, myLongitude));
9.很简单,到此我们就实现了今天我们想实现的所有功能,我们只需要一个activity类就可以完成我们的百度地图demo.代码如下:
/** * 此demo用来展示如何进行驾车、步行、公交路线搜索并在地图使用RouteOverlay、TransitOverlay绘制 * 同时展示如何进行节点浏览并弹出泡泡 */ public class RoutePlanDemo extends Activity implements BaiduMap.OnMapClickListener, OnGetRoutePlanResultListener { //全局变量 private double myLongitude; //经度 private double myLatitude; //纬度 //关于定位的参数 LocationClient mLocClient; boolean isFirstLoc = true;// 是否首次定位 public MyLocationListenner myListener = new MyLocationListenner(); //浏览路线节点相关 Button mBtnPre = null;//上一个节点 Button mBtnNext = null;//下一个节点 int nodeIndex = -1;//节点索引,供浏览节点时使用 RouteLine route = null; OverlayManager routeOverlay = null; boolean useDefaultIcon = false; private TextView popupText = null;//泡泡view //地图相关,使用继承MapView的MyRouteMapView目的是重写touch事件实现泡泡处理 //如果不处理touch事件,则无需继承,直接使用MapView即可 MapView mMapView = null; // 地图View BaiduMap mBaidumap = null; //搜索相关 RoutePlanSearch mSearch = null; // 搜索模块,也可去掉地图模块独立使用 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_routeplan); CharSequence titleLable = "路线规划功能"; setTitle(titleLable); //初始化地图 mMapView = (MapView) findViewById(R.id.map); mBaidumap = mMapView.getMap(); // 开启定位图层 mBaidumap.setMyLocationEnabled(true); mBtnPre = (Button) findViewById(R.id.pre); mBtnNext = (Button) findViewById(R.id.next); mBtnPre.setVisibility(View.INVISIBLE); mBtnNext.setVisibility(View.INVISIBLE); //地图点击事件处理 mBaidumap.setOnMapClickListener(this); // 初始化搜索模块,注册事件监听 mSearch = RoutePlanSearch.newInstance(); mSearch.setOnGetRoutePlanResultListener(this); //TODO 定位功能 // 定位初始化 mLocClient = new LocationClient(this); mLocClient.registerLocationListener(myListener); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true);// 打开gps option.setCoorType("bd09ll"); // 设置坐标类型 option.setScanSpan(1000); mLocClient.setLocOption(option); mLocClient.start(); } /** * 发起路线规划搜索示例 * * @param v */ public void SearchButtonProcess(View v) { //重置浏览节点的路线数据 route = null; mBtnPre.setVisibility(View.INVISIBLE); mBtnNext.setVisibility(View.INVISIBLE); mBaidumap.clear(); PlanNode stNode = PlanNode.withLocation(new LatLng(myLatitude, myLongitude)); //TODO 服务器数据接口 //PlanNode enNode = PlanNode.withLocation(new LatLng(shopLatitude,shopLongitude)); //如果使用服务器传递数据将shop的经纬度替换 //PlanNode enNode = PlanNode.withCityNameAndPlaceName("无锡", editEn.getText().toString()); PlanNode enNode = PlanNode.withCityNameAndPlaceName("无锡", "无锡火车站"); // 实际使用中请对起点终点城市进行正确的设定 if (v.getId() == R.id.drive) { mSearch.drivingSearch((new DrivingRoutePlanOption()) .from(stNode) .to(enNode)); } else if (v.getId() == R.id.transit) { mSearch.transitSearch((new TransitRoutePlanOption()) .from(stNode) .city("无锡") .to(enNode)); } else if (v.getId() == R.id.walk) { mSearch.walkingSearch((new WalkingRoutePlanOption()) .from(stNode) .to(enNode)); } } /** * 节点浏览示例 * * @param v */ public void nodeClick(View v) { if (route == null || route.getAllStep() == null) { return; } if (nodeIndex == -1 && v.getId() == R.id.pre) { return; } //设置节点索引 if (v.getId() == R.id.next) { if (nodeIndex < route.getAllStep().size() - 1) { nodeIndex++; } else { return; } } else if (v.getId() == R.id.pre) { if (nodeIndex > 0) { nodeIndex--; } else { return; } } //获取节结果信息 LatLng nodeLocation = null; String nodeTitle = null; Object step = route.getAllStep().get(nodeIndex); if (step instanceof DrivingRouteLine.DrivingStep) { nodeLocation = ((DrivingRouteLine.DrivingStep) step).getEntrace().getLocation(); nodeTitle = ((DrivingRouteLine.DrivingStep) step).getInstructions(); } else if (step instanceof WalkingRouteLine.WalkingStep) { nodeLocation = ((WalkingRouteLine.WalkingStep) step).getEntrace().getLocation(); nodeTitle = ((WalkingRouteLine.WalkingStep) step).getInstructions(); } else if (step instanceof TransitRouteLine.TransitStep) { nodeLocation = ((TransitRouteLine.TransitStep) step).getEntrace().getLocation(); nodeTitle = ((TransitRouteLine.TransitStep) step).getInstructions(); } if (nodeLocation == null || nodeTitle == null) { return; } //移动节点至中心 mBaidumap.setMapStatus(MapStatusUpdateFactory.newLatLng(nodeLocation)); // show popup popupText = new TextView(RoutePlanDemo.this); popupText.setBackgroundResource(R.drawable.popup); popupText.setTextColor(0xFF000000); popupText.setText(nodeTitle); mBaidumap.showInfoWindow(new InfoWindow(popupText, nodeLocation, null)); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); } @Override public void onGetWalkingRouteResult(WalkingRouteResult result) { if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) { Toast.makeText(RoutePlanDemo.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show(); } if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) { //起终点或途经点地址有岐义,通过以下接口获取建议查询信息 //result.getSuggestAddrInfo() return; } if (result.error == SearchResult.ERRORNO.NO_ERROR) { nodeIndex = -1; mBtnPre.setVisibility(View.VISIBLE); mBtnNext.setVisibility(View.VISIBLE); route = result.getRouteLines().get(0); WalkingRouteOverlay overlay = new MyWalkingRouteOverlay(mBaidumap); mBaidumap.setOnMarkerClickListener(overlay); routeOverlay = overlay; overlay.setData(result.getRouteLines().get(0)); overlay.addToMap(); overlay.zoomToSpan(); } } @Override public void onGetTransitRouteResult(TransitRouteResult result) { if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) { Toast.makeText(RoutePlanDemo.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show(); } if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) { //起终点或途经点地址有岐义,通过以下接口获取建议查询信息 //result.getSuggestAddrInfo() return; } if (result.error == SearchResult.ERRORNO.NO_ERROR) { nodeIndex = -1; mBtnPre.setVisibility(View.VISIBLE); mBtnNext.setVisibility(View.VISIBLE); route = result.getRouteLines().get(0); TransitRouteOverlay overlay = new MyTransitRouteOverlay(mBaidumap); mBaidumap.setOnMarkerClickListener(overlay); routeOverlay = overlay; overlay.setData(result.getRouteLines().get(0)); overlay.addToMap(); overlay.zoomToSpan(); } } @Override public void onGetDrivingRouteResult(DrivingRouteResult result) { if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) { Toast.makeText(RoutePlanDemo.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show(); } if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) { //起终点或途经点地址有岐义,通过以下接口获取建议查询信息 //result.getSuggestAddrInfo() return; } if (result.error == SearchResult.ERRORNO.NO_ERROR) { nodeIndex = -1; mBtnPre.setVisibility(View.VISIBLE); mBtnNext.setVisibility(View.VISIBLE); route = result.getRouteLines().get(0); DrivingRouteOverlay overlay = new MyDrivingRouteOverlay(mBaidumap); routeOverlay = overlay; mBaidumap.setOnMarkerClickListener(overlay); overlay.setData(result.getRouteLines().get(0)); overlay.addToMap(); overlay.zoomToSpan(); } } //定制RouteOverly private class MyDrivingRouteOverlay extends DrivingRouteOverlay { public MyDrivingRouteOverlay(BaiduMap baiduMap) { super(baiduMap); } @Override public BitmapDescriptor getStartMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.drawable.icon_st); } return null; } @Override public BitmapDescriptor getTerminalMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.drawable.icon_en); } return null; } } private class MyWalkingRouteOverlay extends WalkingRouteOverlay { public MyWalkingRouteOverlay(BaiduMap baiduMap) { super(baiduMap); } @Override public BitmapDescriptor getStartMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.drawable.icon_st); } return null; } @Override public BitmapDescriptor getTerminalMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.drawable.icon_en); } return null; } } private class MyTransitRouteOverlay extends TransitRouteOverlay { public MyTransitRouteOverlay(BaiduMap baiduMap) { super(baiduMap); } @Override public BitmapDescriptor getStartMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.drawable.icon_st); } return null; } @Override public BitmapDescriptor getTerminalMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.drawable.icon_en); } return null; } } @Override public void onMapClick(LatLng point) { mBaidumap.hideInfoWindow(); } @Override public boolean onMapPoiClick(MapPoi poi) { return false; } @Override protected void onPause() { mMapView.onPause(); super.onPause(); } @Override protected void onResume() { mMapView.onResume(); super.onResume(); } @Override protected void onDestroy() { mSearch.destroy(); mMapView.onDestroy(); super.onDestroy(); } //TODO 定位相关 /** * 定位SDK监听函数 */ public class MyLocationListenner implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { //取经纬度 myLatitude = location.getLatitude(); myLongitude = location.getLongitude(); // map view 销毁后不在处理新接收的位置 if (location == null || mMapView == null) return; MyLocationData locData = new MyLocationData.Builder() .accuracy(location.getRadius()) // 此处设置开发者获取到的方向信息,顺时针0-360 .direction(100).latitude(location.getLatitude()) .longitude(location.getLongitude()).build(); mBaidumap.setMyLocationData(locData); if (isFirstLoc) { isFirstLoc = false; LatLng ll = new LatLng(location.getLatitude(), location.getLongitude()); MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll); mBaidumap.animateMapStatus(u); } } public void onReceivePoi(BDLocation poiLocation) { } } }
10.根据上面的代码修改自己的代码之后我们就可以运行我们的百度地图demo了,效果如下图所示:
11.至此我们就集成好了百度的定位加线路规划功能, 代码下载地址