百度地图sdk踩坑之旅
来源:互联网 发布:道教里的仙人 知乎 编辑:程序博客网 时间:2024/06/03 15:59
1.写在前面
项目中需要加上路线规划,导航,添加覆盖物,因为我最开始项目中定位我使用的是百度定位,所以为了省事,接着使用百度地图sdk实现这些。这两天踩了很多百度地图的坑,记下来。因为一些原因,后面会说,需求还没做完,所以效果图很简单,如下。
2.坑1,环境配置
对于百度地图sdk的配置我是无语。因为一开始项目中并没打算使用百度地图其他功能,只是准备定位。所以我下载sdk时只是下载了定位的sdk,如图
现在需要加上地图和导航的sdk(后面才知道导航并不需要下载专门的导航sdk,因为地图sdk可以直接调用百度地图客户端或者网页), 所以我一键自定义时,把他们全下载了(包括定位),如图,因为不管什么功能的sdk中jar包的命名是一样的,都是BaiduLBS_Android.jar,所以我如果只下载地图和导航,里面的jar也是这个名字,这是不行的。
全部下载后,得到的lib是这样的,如图。
发现没,这libs里面的只有一个架构armeabi,这里我就有种不好的预感,因为这里面并没有想定位下载下来的一样,分为很多架构,如图
然后将权限,依赖什么的都配置好,因为前面用了定位,所以key已经好了。一运行,发现刚进app定位一直失败,看了下定位失败的错误码报162,一查发现162:请求串密文解析失败,一般是由于客户端SO文件加载失败造成,请严格参照开发指南或demo开发,放入对应SO文件。
果然 ,然后我为了验证把libs全部删了把前面只有定位的lib试了下,发现定位可以。试了很多办法和搜了很多资料,最后没办法我用了很直白的方法解决了。
解决坑1 我发现单独下载地图或者定位里面的libs都很正常,如图
只有单独下载导航的libs不正常,如图
所以我有准备使用三个功能地图,定位,导航的的jar包,和分别下载三个功能的so文件,手动把他们分到一起去,
最后确实成功了,运行后可以定位,而且三个功能的api都可以使用,但是后面发现调用外部地图其实并不需要导航的sdk,所以这上面操作然并卵,但是如果有人需要使用导航的sdk,那这种思路是可以的。
3.百度地图地理编码
因为后面路线规划时需要终点的位置,我觉得使用经纬度比文字描述好点,所以准备将终点位置转成经纬度,这个比较容易,只要知道得出来的百度坐标系。代码如下
实现OnGetGeoCoderResultListener接口,GeoCoder mSearch = null;// 初始化搜索模块,注册事件监听mSearch = GeoCoder.newInstance();mSearch.setOnGetGeoCodeResultListener(this);mSearch.geocode(new GeoCodeOption() .city(address) .address(address));
这里我发现一个有意思的事,api中GeoCodeOption的参数是设置城市和设置地址,但是其实可以写一个参数,如上面.
前面实现了接口,需要重写的两个方法就是返回的结果,代码如下
//获取正向编码规则 @Override public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) { if (geoCodeResult == null || geoCodeResult.error != SearchResult.ERRORNO.NO_ERROR) { //没有检索到结果 Toast.makeText(HomeMenuDetailActivity.this, "没有检索到结果", Toast.LENGTH_SHORT).show(); } //获取地理编码结果 String strInfo = String.format("纬度:%f 经度:%f", geoCodeResult.getLocation().latitude, geoCodeResult.getLocation().longitude); }
4.对终点位置的设置
对终点做了几个设置,1进地图希望以终点为中心。2添加覆盖物。3添加泡泡弹框。
地图页面的布局很简单,就是一个mapview,就不贴了。
1.希望进入地图以终点为中心,使用baidumap的这个方法
setMapStatus(MapStatusUpdate update)改变地图状态
代码很简单,我直接贴代码了
mapView = (MapView) this.findViewById(R.id.bmapView);baiduMap = mapView.getMap();//终点位置对象LatLng llEnd = new LatLng(latidudeB, longtidudeB);MapStatus.Builder builder = new MapStatus.Builder();builder.target(llEnd).zoom(18.0f); baiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
2.对终点添加覆盖物,就是那个icon,代码比较简单,注释也写了,直接上代码
//终点覆盖物图标BitmapDescriptor endMakerIcon = BitmapDescriptorFactory .fromResource(R.mipmap.icon_en);//终点位置LatLng llEnd = new LatLng(latidudeB, longtidudeB);OverlayOptions optionEnd = new MarkerOptions() .position(llEnd) .icon(endMakerIcon);//在地图上添加Marker,并显示baiduMap.addOverlay(optionEnd);
3.那个泡泡弹窗做的有点失败,因为不是很好看,做的好,应该外面包含一张泡泡图片,百度提供一张,但是不适合,而且也应该把矩形的四个角用shape倒角的,这样好看点。
先看下这个xml布局吧,我写的很奇怪,没用weight,而是用数值定死了,因为我开始使用weight运行出来后很难看,见图。我以为是LayoutInflater加载布局时应该还需要个父ViewGroup,但是不管我是用mapview还是最外层的父布局很不行,所以直接写数值了。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="45dp"> <LinearLayout android:background="@color/white" android:gravity="center_vertical" android:orientation="vertical" android:layout_width="220dp" android:layout_height="match_parent"> <TextView android:layout_marginTop="5dp" android:id="@+id/tv_mapview_pop_name" android:layout_marginLeft="10dp" android:textSize="15sp" android:textColor="@color/liteblack" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_marginBottom="5dp" android:id="@+id/tv_mapview_pop_address" android:layout_marginLeft="10dp" android:textSize="13sp" android:lines="1" android:ellipsize="end" android:textColor="@color/grey" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <RelativeLayout android:id="@+id/rl_mapview_pop_navi" android:gravity="center" android:background="@color/colorPrimary" android:layout_width="80dp" android:layout_height="match_parent"> <TextView android:textColor="@color/white" android:textSize="14sp" android:text="导航" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout></LinearLayout>
这个信息窗口,百度api提供了方法,见图
这第二个构造方法三个参数,分别是窗口布局,位置,Y轴偏移量。
代码里写了注释如下,
/** * 终点弹出框泡泡设置 */ public void initMapPopView(){ //创建InfoWindow展示的view View popView = LayoutInflater.from(this).inflate(R.layout.mapview_pop,null); TextView tv_mapview_pop_name = (TextView) popView.findViewById(R.id.tv_mapview_pop_name); TextView tv_mapview_pop_address = (TextView) popView.findViewById(R.id.tv_mapview_pop_address); tv_mapview_pop_name.setText(homeMenuSupplierName); //变量店铺名字 tv_mapview_pop_address.setText(homeMenuSupplierAddress); //变量店铺位置 RelativeLayout rl_mapview_pop_navi = (RelativeLayout) popView.findViewById(R.id.rl_mapview_pop_navi); rl_mapview_pop_navi.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startNavi(); Toast.makeText(BDMenuMapActivity.this,"开始导航",Toast.LENGTH_SHORT).show(); } }); //终点位置 LatLng llEnd = new LatLng(latidudeB, longtidudeB); InfoWindow mInfoWindow = new InfoWindow(popView, llEnd, -70); baiduMap.showInfoWindow(mInfoWindow); }
5.发起路线规划搜索(重要)
先把开始步骤写好,实现接口,获取搜索实例,代码如下
implements OnGetRoutePlanResultListener // 搜索相关RoutePlanSearch mSearch = null; // 搜索模块,也可去掉地图模块独立使用// 初始化搜索模块,注册事件监听mSearch = RoutePlanSearch.newInstance();//设置路线检索监听者mSearch.setOnGetRoutePlanResultListener(this);
实现接口后,有几个方法要重写,其实就是发起路线搜索后的结果,
我这代码里只写了驾车路线规划。首先在这个页面,一定是知道起点和终点的位置了,不管是什么样的形式,经纬度,还是一个string字符串描述。
发起驾车路线规划方法,用它反推,需要什么东西。
mSearch.drivingSearch(drivingOption);
需要这个参数,DrivingRoutePlanOption,而这个对象又有如下方法
DrivingRoutePlanOption currentCity(java.lang.String cityName) 设置当前城市,检索打车信息时必需 DrivingRoutePlanOption from(PlanNode from) 设置起点 DrivingRoutePlanOptionpassBy(java.util.List<PlanNode> wayPoints) 设置途经点 DrivingRoutePlanOption policy(DrivingRoutePlanOption.DrivingPolicy policy) 设置驾车路线规划策略 DrivingRoutePlanOption to(PlanNode to) 设置终点 DrivingRoutePlanOption trafficPolicy(DrivingRoutePlanOption.DrivingTrafficPolicy trafficPolicy) 设置是否支持路况数据
设置起点和终点都涉及到PlanNode对象,它的构造方法有两个
static PlanNode withCityCodeAndPlaceName(int cityCode, java.lang.String placeName)通过地名和城市名确定出行节点信息static PlanNode withCityNameAndPlaceName(java.lang.String city, java.lang.String placeName)通过地名和城市名确定出行节点信息static PlanNode withLocation(LatLng location)通过指定经纬度确定出行节点信息
一般两点驾车路线规划可以有几种选择,这里也可以设置
policy(DrivingRoutePlanOption.DrivingPolicy policy) 设置驾车路线规划策略 ECAR_AVOID_JAM 驾车策略: 躲避拥堵 ECAR_DIS_FIRST 驾乘检索策略常量:最短距离 ECAR_FEE_FIRST 驾乘检索策略常量:较少费用 ECAR_TIME_FIRST 驾乘检索策略常量:时间优先
因为我还想获取,驾车需要的时间,千米,设置如下
currentCity(java.lang.String cityName)设置当前城市,检索打车信息时必需
代码如下
PlanNode stNode = PlanNode.withLocation(new LatLng(latitudeA,longtidueA)); //起点位置 PlanNode enNode = PlanNode.withLocation(new LatLng(latidudeB,longtidudeB)); //终点位置 DrivingRoutePlanOption drivingOption = new DrivingRoutePlanOption(); drivingOption.from(stNode);//设置起点 drivingOption.to(enNode); //设置终点drivingOption.currentCity("长沙市"); //发起驾车路线规划 mSearch.drivingSearch(drivingOption);
在返回的搜索结果中操作,希望路线规划出来后能用覆盖物显示地图上面,这里就有坑2.
坑2
demo中提供了方法设置,如下
// 定制RouteOverly private class MyDrivingRouteOverlay extends DrivingRouteOverlay { public MyDrivingRouteOverlay(BaiduMap baiduMap) { super(baiduMap); } @Override public BitmapDescriptor getStartMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.mipmap.icon_st); } return null; } @Override public BitmapDescriptor getTerminalMarker() { if (useDefaultIcon) { return BitmapDescriptorFactory.fromResource(R.mipmap.icon_en); } return null; } }
但是把方法copy来后DrivingRouteOverlay这个类怎么也找不到,我又不能把demo中的copy过来,万一这里面用了其他的类或者接口呢。所以我用百度搜了下,发现“DrivingRouteOverlay不存在/找不到“都已经成一个词条了。然后发现可以去论坛或者把demo中的一个overlay util包copy到项目中。为什么这个包没放在sdk里面呢,应该百度地图有其他考量吧
所以随便选条路出来,把它显示出来。
route = drivingRouteResult.getRouteLines().get(0); //创建公交路线规划线路覆盖物 DrivingRouteOverlay overlay = new MyDrivingRouteOverlay(baiduMap);// routeOverlay = overlay; //设置公交路线规划数据 overlay.setData((DrivingRouteLine) route); //将公交路线规划覆盖物添加到地图中 overlay.addToMap(); overlay.zoomToSpan();
坑3,打车信息为null
根据api,这DrivingRouteResult可以获取打车信息的。如图
但其实不管是用
TaxiInfo taxiInfo = drivingRouteResult.getTaxiInfo();List<TaxiInfo> taxiInfoList = drivingRouteResult.getTaxiInfos();
都不行,获取对象,对象是null,获取集合也是null。我在论坛搜了下
发现也有人问这种情况,据说是路线搜索时设置参数问题,不用经纬度表示位置,我用这样的参数也试了下还是不行,但是我去百度地图客户端试了下这两个地点,驾车路线有时间个千米显示。前面那个位置是我用百度地图定位获取到的addressstr。我还问了下以前使用百度地图的大佬,也没得到好的结果大佬博客位置
// PlanNode stNode = PlanNode.withCityNameAndPlaceName("长沙市","中国湖南省长沙市芙蓉区万家丽中路1段-95号");// PlanNode enNode = PlanNode.withCityNameAndPlaceName("长沙市", "湖南长沙芙蓉区东郡华城广场A2-1207");
6.启动百度地图导航
这demo中提供很多方法,直接copy就好了,感觉百度地图这demo做的挺好的,很多东西都找得到.。我这里选调百度地图客户端。所以并不需要导航sdk。
/** * 启动百度地图导航(Native) */ public void startNavi() { LatLng pt1 = new LatLng(latitudeA, longtidueA); LatLng pt2 = new LatLng(latidudeB, longtidudeB); // 构建 导航参数 NaviParaOption para = new NaviParaOption() .startPoint(pt1).endPoint(pt2) .startName("长沙市芙蓉区万家丽中路1段-95号").endName("长沙芙蓉区东郡华城广场A2-1207"); try { BaiduMapNavigation.openBaiduMapNavi(para, this); } catch (BaiduMapAppNotSupportNaviException e) { e.printStackTrace(); // showDialog(); } }
- 百度地图sdk踩坑之旅
- 百度地图SDK 踩坑之旅------百度定位OnReceiveLocation没回调,什么都没有。
- 百度地图之SDK定位
- 百度地图定位SDK 之构想
- Android开发之集成百度地图SDK
- 百度地图sdk之 Geocoding API
- ios百度导航SDK,iOS开发之百度地图导航
- 百度地图SDK使用
- 百度地图SDK
- 百度地图SDK使用
- 百度地图SDK-BaseMapDemo
- 百度地图sdk学习心得
- 百度地图SDK 使用
- 百度地图Javascript SDK
- 百度SDK地图定位
- 使用百度地图sdk
- 百度地图SDK-BaseMapDemo
- 集成百度地图sdk
- Python脚本获取Linux系统信息
- python 小例子
- HTML5中table的复杂表格分区
- Java 内部类详解及其练习
- 使用python如何实现Windows定时关机?
- 百度地图sdk踩坑之旅
- 根据中序和后序遍历序列求层序遍历序列
- c++在unix系统上访问ms sqlserver的方法
- "undefined reference to" 问题解决方法
- ZARCHIVE_DECONSTRUCT_INDEX
- EtherType :以太网类型字段及值
- Spring MVC框架select,option和options标签的使用
- MySQL匹配指定字符串的查询
- “排序+计数”实现找顺子功能