基于百度地图sdk的地图app开发(七)

您所在的位置:网站首页 百度地图上报 基于百度地图sdk的地图app开发(七)

基于百度地图sdk的地图app开发(七)

2024-01-20 11:14| 来源: 网络整理| 查看: 265

这是基于百度地图sdk的地图app开发系列博客第七篇

代码仓库位置:https://github.com/YanhuiLu89/lmap.git

上一篇 基于百度地图sdk的地图app开发(六)——路线规划

因为本人是做C++开发,android和java都不熟,这方面知识有说错或者不好的习惯,欢迎赐较。

 

官方参考文档:Android导航SDK

一、工程配置 1.1 在AndroidMainfest.xml中加入以下权限

(指导文档里的权限比这多,前面几个权限在前面几篇文章里,使用百度地图sdk时已经加入了,所以这里只需要加下面这3个就好)

官方文档中授权key配置,在第一篇基于百度地图sdk的地图app开发(一)——开发环境配置与sdk下载里已经做了,所以下面直接到导航SDK核心集成

1.2 导航SDK集成和添加依赖库

将基于百度地图sdk的地图app开发(一)——开发环境配置与sdk下载中下载的onsdk_all.aar、和NaviTts.aar两个文件拷贝到app\libs下,

在build.gradle中添加以下代码

android { // apache包 useLibrary 'org.apache.http.legacy' …… } dependencies { implementation files('libs\\NaviTts.aar') implementation files('libs\\onsdk_all.aar') implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'android.arch.lifecycle:extensions:1.1.1' } 1.3 TTS授权申请

SDK授权申请后,可以继续申请TTS授权。

    1. 以基于百度地图sdk的地图app开发(一)——开发环境配置与sdk下载中提到的SDK授权申请时相同账号登录 http://yuyin.baidu.com/,点击右上角的“控制台“,进入控制台界面,点击左侧导航栏“语音技术”,然后点击创建应用。

     2. 按步骤填入应用名称、包名等信息。

     3. 点击立即创建会生成App ID,就是在开发中初始化TTS能力时传入的参数之一

至此,和导航SDK集成相关的授权申请就完成了。

虽然做了配置,导航没有声音原因目前未知

 

1.4so库的集成

在第一篇基于百度地图sdk的地图app开发(一)——开发环境配置与sdk下载中已经下载了so库(在arm64-v8a、armeabi和armeabi-v7a文件夹中),并且放置到了app/libs目录下

这里只需要在app的Build.gradle里增加以下红框中设置

另外也可以像官方文档中那样。在 main 目录下创建文件夹 jniLibs (如果有就不需要创建了),将下载文件的 armeabi 等相关文件夹复制到这个目录下,这时候就不需要上面红框的设置了。

1.5 Gradle配置

2为了避免Android "64K 引用限制"引起的异常,在app的build.gradle中需要引入multidex包,并进行相关配置,并且导航SDK内部使用了annotationProcessor,同样需要在build.gradle中配置,如下。

defaultConfig { …… // 避免"64K 引用限制" multiDexEnabled true // 导航SDK内部使用了annotationProcessor,需要添加下面代码,防止编译异常 javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } } } 二、导航SDK初始化 2.1、初始化导航sdk

导航sdk初始化接口详细说明

初始化接口init详细说明如: /** * 初始化百度导航. * * @param context 建议是应用的context * @param sdcardRootPath 系统SD卡根目录路径 * @param appFolderName 应用在SD卡中的目录名 * @param naviInitListener 百度导航初始化监听器 */ void init(final Context context, final String sdcardRootPath, final String appFolderName, final INaviInitListener naviInitListener);

在MainActivity的OnCreate函数中添加以下代码进行初始化

//导航初始化 File sdDir = null; boolean sdCardExist = Environment.getExternalStorageState() .equals(android.os.Environment.MEDIA_MOUNTED);//判断sd卡是否存在 if(sdCardExist) { sdDir = Environment.getExternalStorageDirectory();//获取跟目录 } BaiduNaviManagerFactory.getBaiduNaviManager().init(getApplicationContext(), sdDir.toString(), "lmap", new IBaiduNaviManager.INaviInitListener() { @Override public void onAuthResult(int i, String s) { if(i==0) { Toast.makeText(MainActivity.this, "key校验成功!", Toast.LENGTH_SHORT).show(); } else if(i==1) { Toast.makeText(MainActivity.this, "key校验失败, " + s, Toast.LENGTH_SHORT).show(); } } @Override public void initStart() { } @Override public void initSuccess() { Toast.makeText(MainActivity.this, "百度导航引擎初始化成功", Toast.LENGTH_SHORT).show(); // 初始化tts initTTs(); } @Override public void initFailed(int i) { Toast.makeText(MainActivity.this, "百度导航引擎初始化失败", Toast.LENGTH_SHORT).show(); } }); 2.2 初始化tts

增加函数initTTs(),其调用时机为导航sdk初始化成功时调用,见上图initSuccess()接口中,其函数中先初始化,再 注册同步内置tts状态回调

private void initTTs() { File sdDir = null; boolean sdCardExist = Environment.getExternalStorageState() .equals(android.os.Environment.MEDIA_MOUNTED);//判断sd卡是否存在 if(sdCardExist) { sdDir = Environment.getExternalStorageDirectory();//获取跟目录 } BNTTsInitConfig.Builder builder=new BNTTsInitConfig.Builder(); builder.context(getApplicationContext()).sdcardRootPath(sdDir.toString()).appFolderName("lmap").appId(("填入1.3步骤申请的app id")); BaiduNaviManagerFactory.getTTSManager().initTTS( builder.build()); // 注册同步内置tts状态回调 BaiduNaviManagerFactory.getTTSManager().setOnTTSStateChangedListener( new IBNTTSManager.IOnTTSPlayStateChangedListener() { @Override public void onPlayStart() { Log.e("lmap", "ttsCallback.onPlayStart"); } @Override public void onPlayEnd(String speechId) { Log.e("lmap", "ttsCallback.onPlayEnd"); } @Override public void onPlayError(int code, String message) { Log.e("lmap", "ttsCallback.onPlayError"); } } ); } 三、增加导航功能入口

完成了一二步的配置和初始化,就可以开始使用导航功能了

3.1增加开始导航和模拟导航按钮

增加开始导航和模拟导航两个按钮,其布局代码如下

在上一章基于百度地图sdk的地图app开发(六)——路线规划,算路完成描画路线后,设置按钮可见,即在onGetDrivingRouteResult函数最后,添加以下代码

//显示开始导航按钮 Button startNav=findViewById(R.id.startnavi); startNav.setVisibility(View.VISIBLE); Button simNav=findViewById(R.id.simnavi); simNav.setVisibility(View.VISIBLE);

算路完成显示效果如下

 

3.2开始导航和模拟导航按钮的响应函数中启动导航

我的本意是想使用上一章 基于百度地图sdk的地图app开发(六)——路线规划 算出来的路线结果DrivingRouteResult,来进行导航。客户点击选择哪条路线,就把哪条路线传给导航,开始导航。(我之前的开发经验大部分都是这样。)但是看IBNRoutePlanManager只接受点再重新算路,开始导航,并不接受DrivingRouteResult。所以只能画路线前,保存下来目的地,点击开始导航时再重新算一次。

实现步骤,在MainActivity中增加成员变量mDestation

private PoiInfo mDestation=null;

增加设置mDestation的接口

public void setDestation(PoiInfo poi){mDestation=poi;}

在 上一章基于百度地图sdk的地图app开发(六)——路线规划提到的去这里按钮,点击函数中调用设置mDestation的接口

最后在开始导航按钮的click函数调用startNavi参数传true即启动真实导航,在模拟导航按钮的响应函数中调用startNavi,参数传false,即启动模拟导航。代码如下

//增加开始导航按钮的响应 Button startNav=findViewById(R.id.startnavi); startNav.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startNavi(true); } }); Button simNav=findViewById(R.id.simnavi); simNav.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startNavi(false); } });

startNavi接口的实现如下

private void startNavi(boolean isRealNavi) { if(mCurLocation==null||mDestation==null) return; BNRoutePlanNode sNode = new BNRoutePlanNode.Builder() .latitude(mCurLocation.getLatitude()) .longitude(mCurLocation.getLongitude()) .name("我的位置") .description("我的位置") .build(); BNRoutePlanNode eNode = new BNRoutePlanNode.Builder() .latitude(mDestation.getLocation().latitude) .longitude(mDestation.getLocation().longitude) .name(mDestation.name) .description(mDestation.name) .build(); List list = new ArrayList(); list.add(sNode); list.add(eNode); BaiduNaviManagerFactory.getRoutePlanManager().routePlanToNavi( list, IBNRoutePlanManager.RoutePlanPreference.ROUTE_PLAN_PREFERENCE_DEFAULT, null, new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_START: Toast.makeText(MainActivity.this.getApplicationContext(), "算路开始", Toast.LENGTH_SHORT).show(); break; case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_SUCCESS: Toast.makeText(MainActivity.this.getApplicationContext(), "算路成功", Toast.LENGTH_SHORT).show(); break; case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_FAILED: Toast.makeText(MainActivity.this.getApplicationContext(), "算路失败", Toast.LENGTH_SHORT).show(); break; case IBNRoutePlanManager.MSG_NAVI_ROUTE_PLAN_TO_NAVI: Toast.makeText(MainActivity.this.getApplicationContext(), "算路成功准备进入导航", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(MainActivity.this, DemoGuideActivity.class); intent.putExtra("isRealNavi",isRealNavi); startActivity(intent); break; default: // nothing break; } } }); }

以上“算路成功准备进入导航”用到的DemoGuideActivity在第4节部分实现

四、DemoGuideActivity的实现

新增Activity,继承自FragmentActivity(这一点很重要,如果按照默认继承自AppCompatActivity,在调用BaiduNaviManagerFactory.getRouteGuideManager().onCreate(this, config)会崩溃)。

4.1管理百度专业导航生命周期

在MainActivity的onCreate中调用RouteGuideManager的onCreate函数并将返回的view,设置成MainActivity的ContentView,代码如下

//管理专业导航生命周期 Bundle bundle = new Bundle(); // IS_REALNAVI代表导航类型,true表示真实导航,false表示模拟导航,默认是true boolean isRealNavi=getIntent().getBooleanExtra("isRealNavi",true); bundle.putBoolean(BNaviCommonParams.ProGuideKey.IS_REALNAVI,isRealNavi); // IS_SUPPORT_FULL_SCREEN代表是否沉浸式,默认是true bundle.putBoolean(BNaviCommonParams.ProGuideKey.IS_SUPPORT_FULL_SCREEN, true); BNGuideConfig config = new BNGuideConfig.Builder().params(bundle).build(); View view=BaiduNaviManagerFactory.getRouteGuideManager().onCreate(this, config); if (view != null) { setContentView(view); }

在onStart、onResume、onPause、onStop、onDestroy接口中,分别增加以下代码 

BaiduNaviManagerFactory.getRouteGuideManager().onStart(); BaiduNaviManagerFactory.getRouteGuideManager().onResume(); BaiduNaviManagerFactory.getRouteGuideManager().onPause(); BaiduNaviManagerFactory.getRouteGuideManager().onStop(); BaiduNaviManagerFactory.getRouteGuideManager().onDestroy(false); 4.2设置导航监听,增加结束导航处理 设置导航事件监听,在onNaviGuideEnd()中结束当前activity代码如下,其余接口暂时空实现 //设置导航事件监听 BaiduNaviManagerFactory.getRouteGuideManager().setNaviListener(new IBNaviListener() { //..其余一些空实现接口 @Override public void onNaviGuideEnd() { finish(); } });

设置导航view监听,在onNaviBackClick()内终止导航,其余接口空实现

//设置导航视图监听 BaiduNaviManagerFactory.getRouteGuideManager().setNaviViewListener(new IBNaviViewListener() { //。。。。一些空实现接口。。。。 @Override public void onNaviBackClick() { BaiduNaviManagerFactory.getRouteGuideManager().stopNavi(); } //。。。一些空实现接口。。。。。 });

程序效果,以下分别为真实导航、模拟导航、退出导航的效果

             

五、解决遇到的问题 5.1 jni接口找不到实现No implementation found for......

错误log如下

No implementation found for boolean com.baidu.navisdk.jni.nativeif.JNIGuidanceControl.SetRotateMode(int) (tried Java_com_baidu_navisdk_jni_nativeif_JNIGuidanceControl_SetRotateMode and Java_com_baidu_navisdk_jni_nativeif_JNIGuidanceControl_SetRotateMode__I)         at com.baidu.navisdk.jni.nativeif.JNIGuidanceControl.SetRotateMode(Native Method)

如果集成so库没有问题,出现这个问题多半是要更新库,我这里是更新库之后ok.

5.2 BaiduNaviManagerFactory.getRouteGuideManager().onCreate(this, config)崩溃

崩溃log如下

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.ViewGroup.findViewById(int)' on a null object reference

原因:DemoGuideActivity不能继承自AppCompatActivity

修改:改成public class DemoGuideActivity extends FragmentActivity ,崩溃问题解决

 

六、遗留问题没有声音

导航没有声音

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3