百度地图_导航和TTS语音播报的实现

前言

从小白一步步开始,很多资源是很久以前的,而且没有操作配套截图和资源分享。现在本踩过了很多坑,现在开发完成后决定重新写一份教程,希望能借此帮助到许多其他有这方面需求的人。
精力有限,会尽可能详细。
本文同项目同步完成,已经是做过好几个类似项目工程,但还是出了一些小问题,已经附上解决方法,本文中所用到资源文件已经附上下载链接,也可以自行去百度地图开发者官网去下载,不过由于版本更新很快,若使用本文开发还是强烈推荐使用本文提供链接进行下载,尤其是SDK,如果在构建项目中出一些问题很可能是SDK已经被官方更新导致,本文的操作步骤只在本人开发时保证有效,随着时间推移可能已经不适合,本人也不可能一直维护更新操作步骤
另外,源码已在文末给出下载地址,若导入源码出现问题很大程度上可以考虑是Android Studio(AS)和Gradle版本的问题,请自行百度去解决

还想说的是,若可以编译生成了APK,在虚拟机或实体设备运行中出现问题,给大家分享的一些本人开发百度地图调试的主要思路:
1.首先请自行百度学习一下AS的BUG调试,同其他的IDE程序一样,AS也可以标识代码运行到哪一步出现问题
2.找到出问题的代码,BUG调试里会有报错原因提示,可以直接复制报错原因,百度查找解决方法,大概率会有类似的解决帖子

相信按照本文可以解决绝大数问题,每个人的开发运行环境不同,不可避免会出一些其他问题,若还有其他问题,本人只能提供一些建议,具体措施可能还是需要你自己去解决,若分享链接失效,文末附上了**联系方式(会及时查看好友申请,同时请注明添加理由,否则不通过申请)**或者评论区冒泡。

于2020.3.7 19:16更新了失效链接,重新编辑了前言

注:
本文仅在前文的基础上只新增了步行导航和TTS语音播报。

参考官方文档(导航和TTS)步骤:
配置AndroidManifest.xml文件:

<!-- 读写sd卡 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!-- 写sd卡 --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.ACCESS_GPS"/><!-- 获取精确gps位置 --><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/><!-- 获取粗略位置 --><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><!-- 允许程序访问额外的定位提供者指令获取模拟定位信息 --><uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/><!-- 网络链接 --><uses-permission android:name="android.permission.INTERNET"></uses-permission><!-- 获取网络状态 --><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission><!-- 更改wifi连状态 --><uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/><!-- 获取wifi状态 --><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>


布局更新:

<Buttonandroid:id="@+id/but_Navi"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="导航"android:layout_marginLeft="0dp"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintTop_toTopOf="parent"android:layout_marginTop="209dp"/>


类包添加(导航资源提取码:wng5):

复制添加到java目录下:

报错处理:

直接删除,会自动引入正确的R;
若运行报如下错:

点击报错项,会自动跳转到有错误的代码处,也是上述处理即可;

这是缺少资源文件所致,添加如下资源文件:

已经提前处理,直接把上述文件夹对工程中相应文件夹进行覆盖即可:

build.gradle文件更新:

ndk {abiFilters "armeabi", "x86", "x86_64", "mips64", "mips"}


MainActivity文件更新(类包会自动导入):

public class MainActivity extends AppCompatActivity implements View.OnClickListener{private MapView mMapView = null;private BaiduMap mBaiduMap = null;private Context context;//定位相关private double mLatitude;private double mLongtitude;//方向传感器private MyOrientationListener mMyOrientationListener;private float mCurrentX;//自定义图标private BitmapDescriptor mIconLocation;private LocationClient mLocationClient;public BDAbstractLocationListener myListener;private LatLng mLastLocationData;private boolean isFirstin = true;// 路线规划相关private RoutePlanSearch mSearch = null;//导航相关private static final String APP_FOLDER_NAME = "MyBNDTSDK-Api";private String mSDCardPath = null;private static final String[] authBaseArr = {Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.ACCESS_FINE_LOCATION};private static final int authBaseRequestCode = 1;private boolean hasInitSuccess = false;static final String ROUTE_PLAN_NODE = "routePlanNode";private BNRoutePlanNode mStartNode = null;private LatLng mDestLocationData;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);SDKInitializer.initialize(getApplicationContext());setContentView(R.layout.activity_main);SDKInitializer.setCoordType(CoordType.BD09LL);this.context = this;mMapView = (MapView) findViewById(R.id.bmapView);//获取地图控件引用mBaiduMap = mMapView.getMap();initMyLocation();initPoutePlan();initLongClick();button();//初始化导航相关if (initDirs()) {initNavi();}}protected void onStart() {super.onStart();//开启定位mBaiduMap.setMyLocationEnabled(true);if (!mLocationClient.isStarted())mLocationClient.start();//开启方向传感器mMyOrientationListener.start();}@Overrideprotected void onResume() {super.onResume();mMapView.onResume();}@Overrideprotected void onPause() {super.onPause();mMapView.onPause();}@Overrideprotected void onStop() {super.onStop();//停止定位mBaiduMap.setMyLocationEnabled(false);mLocationClient.stop();//停止方向传感器mMyOrientationListener.stop();}@Overrideprotected void onDestroy() {super.onDestroy();mBaiduMap.setMyLocationEnabled(false);mMapView.onDestroy();mMapView = null;mSearch.destroy();}@Overridepublic void onClick(View v) {SDKInitializer.initialize(getApplicationContext());switch (v.getId()) {case R.id.but_Loc: {centerToMyLocation(mLatitude, mLongtitude);break;}case R.id.but_RoutrPlan: {StarRoute();break;}case R.id.but_Navi: {if(mDestLocationData == null){Toast.makeText(MainActivity.this, "导航:长按设置目标地点", Toast.LENGTH_SHORT).show();return;}routeplanToNavi();break;}}}//按钮响应private void button() {//按钮Button mbut_Loc = (Button) findViewById(R.id.but_Loc);Button mbut_RoutrPlan = (Button) findViewById(R.id.but_RoutrPlan);Button mbut_Navi = (Button) findViewById(R.id.but_Navi);//按钮处理mbut_Loc.setOnClickListener(this);mbut_RoutrPlan.setOnClickListener(this);mbut_Navi.setOnClickListener(this);}//定位private class MyLocationListener extends BDAbstractLocationListener {@Overridepublic void onReceiveLocation(BDLocation location) {//mapView 销毁后不在处理新接收的位置if (location == null || mMapView == null){return;}MyLocationData locData = new MyLocationData.Builder().accuracy(location.getRadius())// 此处设置开发者获取到的方向信息,顺时针0-360.direction(mCurrentX).latitude(location.getLatitude()).longitude(location.getLongitude()).build();mBaiduMap.setMyLocationData(locData);//设置自定义图标MyLocationConfiguration config = newMyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, mIconLocation);mBaiduMap.setMyLocationConfiguration(config);//更新经纬度mLatitude = location.getLatitude();mLongtitude = location.getLongitude();//设置起点mLastLocationData = new LatLng(mLatitude, mLongtitude);if (isFirstin) {centerToMyLocation(location.getLatitude(), location.getLongitude());if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位结果Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 网络定位结果Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果Toast.makeText(context, "定位:"+location.getAddrStr(), Toast.LENGTH_SHORT).show();} else if (location.getLocType() == BDLocation.TypeServerError) {Toast.makeText(context, "定位:服务器错误", Toast.LENGTH_SHORT).show();} else if (location.getLocType() == BDLocation.TypeNetWorkException) {Toast.makeText(context, "定位:网络错误", Toast.LENGTH_SHORT).show();} else if (location.getLocType() == BDLocation.TypeCriteriaException) {Toast.makeText(context, "定位:手机模式错误,请检查是否飞行", Toast.LENGTH_SHORT).show();}isFirstin = false;}}}//初始化定位private void initMyLocation() {//缩放地图MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);mBaiduMap.setMapStatus(msu);//开启定位mBaiduMap.setMyLocationEnabled(true);//声明LocationClient类mLocationClient = new LocationClient(this);//通过LocationClientOption设置LocationClient相关参数LocationClientOption option = new LocationClientOption();option.setOpenGps(true); // 打开gpsoption.setCoorType("bd09ll"); // 设置坐标类型option.setIsNeedAddress(true);//设置是否需要地址信息option.setScanSpan(1000);//设置locationClientOptionmLocationClient.setLocOption(option);myListener = new MyLocationListener();//注册监听函数mLocationClient.registerLocationListener(myListener);//初始化图标mIconLocation = BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps);initOrientation();//开始定位mLocationClient.start();}//回到定位中心private void centerToMyLocation(double latitude, double longtitude) {mBaiduMap.clear();mLastLocationData = new LatLng(latitude, longtitude);MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(mLastLocationData);mBaiduMap.animateMapStatus(msu);}//传感器private void initOrientation() {//传感器mMyOrientationListener = new MyOrientationListener(context);mMyOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {@Overridepublic void onOrientationChanged(float x) {mCurrentX = x;}});}//路线规划初始化private void initPoutePlan() {mSearch = RoutePlanSearch.newInstance();mSearch.setOnGetRoutePlanResultListener(listener);}// 路线规划模块public OnGetRoutePlanResultListener listener = new OnGetRoutePlanResultListener() {@Overridepublic void onGetWalkingRouteResult(WalkingRouteResult result) {if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {Toast.makeText(MainActivity.this, "路线规划:未找到结果,检查输入", Toast.LENGTH_SHORT).show();//禁止定位isFirstin = false;}assert result != null;if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {// 起终点或途经点地址有岐义,通过以下接口获取建议查询信息result.getSuggestAddrInfo();return;}if (result.error == SearchResult.ERRORNO.NO_ERROR) {mBaiduMap.clear();Toast.makeText(MainActivity.this, "路线规划:搜索完成", Toast.LENGTH_SHORT).show();WalkingRouteOverlay overlay = new WalkingRouteOverlay(mBaiduMap);overlay.setData(result.getRouteLines().get(0));overlay.addToMap();overlay.zoomToSpan();}//禁止定位isFirstin = false;}@Overridepublic void onGetTransitRouteResult(TransitRouteResult var1) {}@Overridepublic void onGetMassTransitRouteResult(MassTransitRouteResult var1) {}@Overridepublic void onGetDrivingRouteResult(DrivingRouteResult result) {}@Overridepublic void onGetIndoorRouteResult(IndoorRouteResult var1) {}@Overridepublic void onGetBikingRouteResult(BikingRouteResult var1) {}};//开始规划private void StarRoute() {SDKInitializer.initialize(getApplicationContext());// 设置起、终点信息PlanNode stNode = PlanNode.withCityNameAndPlaceName("北京", "西二旗地铁站");PlanNode enNode = PlanNode.withCityNameAndPlaceName("北京", "百度科技园");mSearch.walkingSearch((new WalkingRoutePlanOption()).from(stNode).to(enNode));}//导航//获取Sdcard目录private String getSdcardDir() {if (Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) {return Environment.getExternalStorageDirectory().toString();}return null;}//初始化导航目录private boolean initDirs() {mSDCardPath = getSdcardDir();if (mSDCardPath == null) {return false;}File f = new File(mSDCardPath, APP_FOLDER_NAME);if (!f.exists()) {try {f.mkdir();} catch (Exception e) {e.printStackTrace();return false;}}return true;}private boolean hasBasePhoneAuth() {PackageManager pm = this.getPackageManager();for (String auth : authBaseArr) {if (pm.checkPermission(auth, this.getPackageName()) != PackageManager.PERMISSION_GRANTED) {return false;}}return true;}//初始化语音播报private void initTTS() {// 使用内置TTSBaiduNaviManagerFactory.getTTSManager().initTTS(getApplicationContext(),getSdcardDir(), APP_FOLDER_NAME, NormalUtils.getTTSAppID());// 注册同步内置tts状态回调BaiduNaviManagerFactory.getTTSManager().setOnTTSStateChangedListener(new IBNTTSManager.IOnTTSPlayStateChangedListener() {@Overridepublic void onPlayStart() {Log.e("BNSDKDemo", "ttsCallback.onPlayStart");}@Overridepublic void onPlayEnd(String speechId) {Log.e("BNSDKDemo", "ttsCallback.onPlayEnd");}@Overridepublic void onPlayError(int code, String message) {Log.e("BNSDKDemo", "ttsCallback.onPlayError");}});// 注册内置tts 异步状态消息BaiduNaviManagerFactory.getTTSManager().setOnTTSStateChangedHandler(new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {Log.e("BNSDKDemo", "ttsHandler.msg.what=" + msg.what);}});}//初始化导航private void initNavi() {// 申请权限if (android.os.Build.VERSION.SDK_INT >= 23) {if (!hasBasePhoneAuth()) {this.requestPermissions(authBaseArr, authBaseRequestCode);return;}}BaiduNaviManagerFactory.getBaiduNaviManager().init(this,mSDCardPath, APP_FOLDER_NAME, new IBaiduNaviManager.INaviInitListener() {@Overridepublic void onAuthResult(int status, String msg) {String result;if (0 == status) {result = "key校验成功!";} else {result = "key校验失败, " + msg;}Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();}@Overridepublic void initStart() {Toast.makeText(MainActivity.this, "导航引擎初始化开始", Toast.LENGTH_SHORT).show();}@Overridepublic void initSuccess() {Toast.makeText(MainActivity.this, "导航引擎初始化成功", Toast.LENGTH_SHORT).show();hasInitSuccess = true;// 初始化ttsinitTTS();}@Overridepublic void initFailed() {Toast.makeText(MainActivity.this, "导航引擎初始化失败", Toast.LENGTH_SHORT).show();}});}//添加导航目的地图标private void addDestInfoOverlay(LatLng latLng) {mBaiduMap.clear();OverlayOptions options = new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_geo)).zIndex(5);mBaiduMap.addOverlay(options);}//坐标转换public static BDLocation bd2gcj(BDLocation loc) {return LocationClient.getBDLocationInCoorType(loc,BDLocation.BDLOCATION_BD09LL_TO_GCJ02);}//导航算路private void routeplanToNavi() {final int coType = BNRoutePlanNode.CoordinateType.GCJ02;if (!hasInitSuccess) {Toast.makeText(MainActivity.this, "还未初始化!", Toast.LENGTH_SHORT).show();}BDLocation srcBdLocation = new BDLocation();srcBdLocation.setLatitude(mLastLocationData.latitude);srcBdLocation.setLongitude(mLastLocationData.longitude);BDLocation srcGcj = bd2gcj(srcBdLocation);BDLocation destBdLocation = new BDLocation();destBdLocation.setLatitude(mDestLocationData.latitude);destBdLocation.setLongitude(mDestLocationData.longitude);BDLocation destGcj = bd2gcj(destBdLocation);BNRoutePlanNode sNode = new BNRoutePlanNode(srcGcj.getLongitude(),srcGcj.getLatitude(),"我的地点",null,coType);BNRoutePlanNode eNode = new BNRoutePlanNode(destGcj.getLongitude(),destGcj.getLatitude(),"目标地点",null,coType);mStartNode = sNode;List<BNRoutePlanNode> list = new ArrayList<>();list.add(sNode);list.add(eNode);BaiduNaviManagerFactory.getRoutePlanManager().routeplanToNavi(list,IBNRoutePlanManager.RoutePlanPreference.ROUTE_PLAN_PREFERENCE_DEFAULT,null,new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_START:Toast.makeText(MainActivity.this, "导航:算路开始", Toast.LENGTH_SHORT).show();break;case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_SUCCESS:Toast.makeText(MainActivity.this, "导航:算路成功", Toast.LENGTH_SHORT).show();break;case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_FAILED:Toast.makeText(MainActivity.this, "导航:算路失败", Toast.LENGTH_SHORT).show();break;case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_TO_NAVI:Toast.makeText(MainActivity.this, "导航:算路成功准备进入导航", Toast.LENGTH_SHORT).show();Intent intent = new Intent(MainActivity.this,DemoGuideActivity.class);Bundle bundle = new Bundle();bundle.putSerializable(ROUTE_PLAN_NODE, mStartNode);intent.putExtras(bundle);startActivity(intent);break;default:// nothingbreak;}}});}//长按处理private void initLongClick() {mBaiduMap.setOnMapLongClickListener(new BaiduMap.OnMapLongClickListener() {@Overridepublic void onMapLongClick(LatLng latLng) {Toast.makeText(context,"导航:设置目的地成功", Toast.LENGTH_LONG).show();mDestLocationData = latLng;addDestInfoOverlay(latLng);}});}
}

在AndroidManifest.xml中声明定位的activity组件:

<activity android:name="com.sdkdemo.newif.DemoGuideActivity"/><activity android:name="com.sdkdemo.liteapp.LiteActivity"/>


TTS语音激活(语音激活):





这里需要的是App ID

在MainActivity中找到如下代码处:

将鼠标移动到箭头所指的getTTSAppID()方法上,按住ctrl键,鼠标变成小手的形状左键点进去跳转到如下,把获取到的App ID输入即可:

此时导航和TTS语音播报也实现了,便可以运行了,效果如图:

长按地图设置目的地(下图粉红点处为目的地):

此时点击导航按钮(由于是晚上,自动暗色模式):

全览:

点击更多:

点击更多设置:

自点击导航键全程伴有TTS语音,图片无法演示,这里就不展示了。

工程按照步骤是能自己建好自己工程项目的
工程开发,文章撰写耗费不少精力,很多资源收集不易。若需要源码,给出源码下载链接(按需下载,前一节功能被后一节包含,需要全部功能的朋友直接下载最后一节【导航和TTS】的源码即可):
源码
生成的可运行apk:app-debug.apk 提取码:dy7h

2019-详细Android Studio开发百度地图(5)—百度地图_导航和TTS语音播报的实现相关推荐

  1. android studio开发环境搭建,国内服务器代理下载android sdk

    android studio开发环境搭建 1,百度android studio,下载安装: 2,启动Fetching Android SDK component information http:// ...

  2. android百度地图定位自定义图标,百度地图SDK集成及根据坐标实现定位(android studio开发)...

    百度地图SDK集成及根据坐标实现定位(android studio开发) 百度地图SDK集成及根据坐标实现定位(android studio开发) 1.下载百度地图SDK 链接:http://lbsy ...

  3. (超多图)基于Android studio开发的一个简单入门小应用(超级详细!!)(建议收藏)

    基于Android studio开发的一个简单入门小应用 一.前言 二.前期准备 三.开发一个小应用 五.运行应用 一.前言 在暑假期间,我学习JAVA基础,为了能早日实现自己用代码写出一个app的& ...

  4. Android Studio开发(六)短距离无线通信——蓝牙通信

    Android Studio开发(六)短距离无线通信--蓝牙通信 Android Studio开发(六)蓝牙通信 一.任务需求 二.短距离无线通信技术(Short-Distance Wirleless ...

  5. 《Android Studio开发实战 从零基础到App上线》第一版的资源下载和内容勘误

    资源下载 下面是<Android Studio开发实战 从零基础到App上线>(第一版)一书用到的工具和代码资源: 1.本书使用的Android Studio版本为2.2.3,因为Andr ...

  6. 《Android Studio开发实战 从零基础到App上线(第2版)》资源下载和内容勘误

    资源下载 下面是<Android Studio开发实战 从零基础到App上线(第2版)>一书用到的工具和代码资源: 1.本书使用的Android Studio版本为3.2,最新的安装包可前 ...

  7. 《Android Studio开发实战 从零基础到App上线(第3版)》资源下载和内容勘误

    资源下载 下面是<Android Studio开发实战 从零基础到App上线(第3版)>一书用到的工具和代码资源: 1.本书使用的Android Studio版本为Android Stud ...

  8. SuperMap iMobile+Android studio开发入门(二)——超图示例代码运行

    背景:这里运行的是"产品入门"的"基于Android studio开发移动GIS程序"的"开发三维移动GIS程序",本篇对超图帮助文档进行了 ...

  9. 《Android Studio开发实战 从零基础到App上线》本书内容问题答疑

    1.关于学习本书之前是否需要Java基础 问题:看安卓开发教程书需要很扎实的java基础吗? 回答:本书的零基础指的是安卓零基础,不是Java零基础,所以看本书之前需要一定的Java基础,基本的变量声 ...

最新文章

  1. reid2019-2021
  2. JVM优化之调整大内存分页(LargePage)
  3. Thread Safety in the Standard C++ Library
  4. .NET简谈插件系统开发模式
  5. SpringCloud 从菜鸟到大牛之六 消息和异步 MQ
  6. 安卓学习笔记39:浏览网页、网页与安卓通信
  7. @WebFilter注解
  8. PHP在线支付类集锦(银联支付宝手机支付宝微信等)
  9. BULK INSERT, 实战手记:让百万级数据瞬间导入SQL Server
  10. ASP.NET Web API 路由 (上)
  11. 51单片机c语言算法大全,C语言实现51单片机中的PID算法
  12. XP突然弹出“automation 服务器不能创建对象”的有效解决方法--win10专业版
  13. matlab p文件转码 matlab pcode文件 将matlab中的p文件转为m文件工具
  14. 【Python 23】52周存钱挑战3.0(循环计数for与range)
  15. 多多客id是什么意思_【多多情报学堂】拼多多id是什么?拼多多店铺id在哪里看?...
  16. R语言read.csv()读入行不规则数据
  17. 职高 计算机应用与基础测试卷,职高二计算机应用基础期末测试.doc
  18. TikTok运营11个常见问题总结
  19. 水滴 Java开发(一面)42min
  20. CLIP4Clip: An Empirical Study of CLIP for End to End Video Clip Retrieval

热门文章

  1. html标签图片填充背景色快捷键,ps中填充颜色的快捷键是什么?
  2. js mp4解码合并成ffmpeg
  3. AI趋势下,小布助手的进化论
  4. php-java-net-python-爱心公益网站()计算机毕业设计程序
  5. HIS软件项目布置的学习day01
  6. ROG 幻16无线网卡驱动无法更新
  7. CentOs7 安装绿色版Nginx并配置开机启动
  8. Linux驱动移植USB网卡r8156驱动(详细)总结
  9. 可以缩放平移的时间刻度尺,方便自定义UI需求。仿萤石云历史录像时间轴
  10. Codeforces Round #578 (Div. 2) 题解报告