由于本人负责的app需要增加导航及地图功能,因此毫不犹豫的选择了百度的LBS SDK,因为他大而全嘛。本文仅记录导航相关的问题。
我是从百度导航sdk1.0版本开始着手的,当时只是技术评估,正在测试其demo的时候发现出2.0版本了。暂且这说说1.0版本的大致功能:
1.能手动规划路线,获取算路的的路况信息返回,也就是路线详情类:
com.baidu.navisdk.model.datastruct.RoutePlanResultItem
该类主要属性为:
mResId - ICON资源id
nodeDesc - 路线规划描述
nodeDescNight - 路线规划描述 夜间描述
bubleDesc - 下一段路名
longitude - 经度
latitude - 纬度
2.能手动控制地图view的生成及显示,也即:
com.baidu.nplatform.comapi.map.MapGLSurfaceView
3. 能手动控制导航进行
4.导航时允许第三方TTS实现导航语音播报
当时还不是太熟悉1.0的sdk就直接迁移到2.0了,初步了解后感觉1.0版本开放的功能还是挺有限的,相比百度自己的导航app真是弱爆了,根本不可能满足公司的需求,
下面说说公司的变态需求(真把自己当百度来定的),主要为:
1.查询路况,最好能查询任意一条路的路况。(我的回复:没门,百度没有开放这种接口,最多能获取规划完路线的路段的路况,仅限RoutePlanResultItem的属性,拥堵信息都没有啊!!!)
2.获取导航时的各种信息:当前车速,当前路段名,下一个导航提示,限速信息,路线全程展示等等,
3.导航前展示多条路线,可以让用户自由选一条,类似百度导航,点选后启动导航。
4.如果可以,要实现想百度导航那样的离线导航,如果不行可以暂时不考虑。
总的来说就一句话,百度导航有的他都想有,连ui也直接让我仿造着百度导航来就行了。当时真是无奈地表示亚历山大,但再怎么无奈也得熟悉一下百度导航的sdk才能对他们的需求作评估,能不能做啊,点开百度导航sdk2.0版本的api,差点没吐血,从api来看,2.0版本开放的功能还没1.0多,我概括一下2.0版本api的意图:你传入起始点和途经点给我就可以了,其它没你什么事了,调用方法启动我就可以了,哦,对了,你们还可以在导航地图上增加自定义的view哦,这个是新功能哦!想从api查询各种信息,门都没有。然后我就想去百度的官方论坛咨询,这个狗屁论坛根本就是摆设,即使骂声一片百度也不会鸟你,最多的回复是:百度导航sdk不支持这种功能。
最后实在没办法,解包百度导航sdk的jar包看源码咯,令人惊喜的是,从源码中得到的信息还真不少,以下是我的发现:
关于规划路线、获取路况信息即切换路线的问题:
2.0API是没有告诉你怎样手动规划路线并得到结果的,但1.0有啊,方法其实没变,只是api不给你看,算路方式和1.0大同小异:
ArrayList<RoutePlanNode> nodes= ArrayList<RoutePlanNode>(); nodes.add(起点); nodes.add(终点); //routePlanObserver作为观察者接收算路结果 BNRoutePlaner.().setObserver(routePlanObserver); BNRoutePlaner.().setCalcPrference(算路方式); BNRoutePlaner.().setPointsToCalcRoute(nodes,1, false, (String) null, 0); BNRoutePlanObserver routePlanObserver=new BNRoutePlanObserver(){ @Override public void update(BNSubject bnSubject, int type, int event, Object o) { Log.e(TAG, "BaiduRoutePlanManager>>update"); if (type == 1) { if (event == 2) { Log.e(TAG, "百度导航算路成功"); //RoutePlanModel类下面会详细说明,里面包含了路线的详细信息 RoutePlanModel mRoutePlanModel = (RoutePlanModel) NaviDataEngine.getInstance().getModel("RoutePlanModel"); //该方法获取的值为算路返回的路线总数,下面会详细说明 int routeCnt=BNRoutePlaner.getInstance().getRouteCnt(); BNMapController.getInstance().setLayerMode(MapParams.Const.LayerMode.MAP_LAYER_MODE_ROUTE_DETAIL_FOR_NAVI); BNMapController.getInstance().updateLayer(MapParams.Const.LayerType.MAP_LAYER_TYPE_ROUTE); } else if (event == 3 || event == 6 || event == 18 || event == 19) { Log.e(TAG, "百度导航算路失败"); } } } }
关于RoutePlanModel 类,他是public的,存放规划完的路线详情的,它存放在NaviDataEngine单态类中,只要你没有手动删除,始终维持一个RoutePlanModel 对象实例,讲一下里面几个重要的方法:
public ArrayList<RoutePlanResultItem> getRouteNodeData()
该方法返回路段集合,RoutePlanResultItem的属性较1.0版本有了更新,属性增加了一个RoadCondition,即拥堵信息,该属性取值:0-4,0代表无效或者未知(地图显示蓝色),1代表畅通(地图显示绿色),2代表行驶缓慢(黄色),3代表拥堵(红色),4代表严重拥堵(深红),也就是说,只要规划完路线,就能获取路线上各段路的拥堵信息
public void parseRouteResult(Context context, Bundle bundle)
该方法十分有用,BNRoutePlaner.getInstance().getRouteCnt()或者RoutePlanModel 的getRouteCnt()都能获取计算路线的总数C,如下图的所示(C=2):
算路完成默认是选第1条,如果要选第(i+1)条,即把地图第二条路点亮,并用第(i+1)条路导航,代码是这样实现的,调用BNRoutePlaner.getInstance().selectRoute(i);i<C。
注意即使你selectRoute了其他路线,从NaviDataEngine获取的RoutePlanModel 存储的仍然是第1条路线的信息,要怎么获取第(i+1)条的路线信息呢?这就需要用到parseRouteResult方法了,如果不想覆盖NaviDataEngine维持的RoutePlanModel ,你可以自己new一个RoutePlanModel 实例,然后调用parseRouteResult方法把第(i+1)条路线的信息解析并保存进去。parseRouteResult方法的第一个参数不解释,第二参数的获取方法如下:
Bundle bundle=Bundle(); BNRoutePlaner.getInstance().getRouteInfo(i, bundle);//获取第(i+1)条路的路线信息
导航中的各种信息获取
1.获取当前道路:RGSimpleGuideModel.getInstance().getCurRoadName();
2.获取当前车速:RGSimpleGuideModel.getInstance().getCurCarSpeed();
3.获取下一步怎么走:RGSimpleGuideModel.getInstance().getNextGuidanceChineseWord();
4.获取限速信息:RGAssistGuideModel.getInstance().getCurLimitSpeed();
5.导航中显示全程路线:
View mTotalFullviewPanel=RGMapModeViewController.getInstance().getView().findViewById(1711866150); if(mTotalFullviewPanel!=null){ Log.i(TAG,"mTotalFullviewPanel.callOnClick()"); mTotalFullviewPanel.callOnClick(); }
还有获取各种信息就不一一举例了,查看jar包的源码就能大致知道。
关于TTS
由于本人之前对比过国内几大语音服务厂商的sdk,综合且客观地说,百度的TTS做的特别差,我公司用的是讯飞的sdk,感觉云知声都比百度的要好。因此百度导航语音播报这一块建议还是别用百度的了。
离线导航
百度导航sdk在老版本中是允许下载离线导航资源包的,如百度导航app,但在新版本中已经不支持了。但要实现还是有办法的,就是稍微麻烦一点,详情就不说了。