Kotlin - 百度导航Demo,我们一起来踩坑!
背景
项目开发中,我们总是离不开定位、地图这些功能,当然有时候有了地图,那么导航就显得很有必要了。现在让我们开启百度导航吧!
第一步:磨刀不误砍柴工,获得你需要的SDK包
下载地址:百度LBS导航SDK
首先我们得从官网采集我们需要的百度LBS开发包,此处就暂时省略啦!
*注意:要使用百度TTS语音,我们需要注册百度导航TTS白名单,否则我们的导航器可是不会吭声的哦!(当然,你自己集成了其他TTS库除外)
第二步:不积洼步,不足以至千里。学习他人经验,事半功倍
配置说明:百度LBS配置
SDK均已按照官方配置好了,现在我们需要做得就是看别人怎么写的 -- 查看官方导航DEMO源代码。
从官方Demo中可以看出,导航流程大致如下:
初始化SDK ---> 初始化导航配置参数 ---> 规划导航路线 -->开始导航
因此我们可以把官方导航Demo修改一下,直接拿来用!
下面是我总结的一个工具类,仅供参考:
class BaiduMapNavigator private constructor(val activity: Activity) {
companion object {
@JvmField
val ROUTE_PLAN_NODE = "routePlanNode"
@JvmField
var isBaiduNaviInitSuccess: Boolean = false
@SuppressLint("StaticFieldLeak")
@JvmField
var baiduNavi: BaiduMapNavigator? = null
@JvmStatic
fun getInstance(context: Activity): BaiduMapNavigator? {
if (baiduNavi == null) {
synchronized(BaiduMapNavigator::class.java) {
baiduNavi = BaiduMapNavigator(context)
}
}
return baiduNavi
}
}
private val eventListerner: BaiduNaviManager.NavEventListener
= BaiduNaviManager.NavEventListener { what, arg1, arg2, bundle -> BNEventHandler.getInstance().handleNaviEvent(what, arg1, arg2, bundle) }
/** 初始化导航 **/
fun initNavigator(context: Context, startNaviName: String, endNaviName: String, naviLatLng: Array<LatLng>) {
val loadingDialog: MaterialProgressDialog? = DialogUtil.initAndShow(context, MaterialProgressDialog::class.java)
loadingDialog?.setLoadingText("正在初始化...")
if (!isBaiduNaviInitSuccess) {
var authinfo: String?
val mSDCardPath = SysData.MAIN_APP_DIRECTORY
File(mSDCardPath, "EdumapNavi").mkdirs()
BaiduNaviManager.getInstance().init(activity, mSDCardPath, "EdumapNavi", object : BaiduNaviManager.NaviInitListener {
override fun onAuthResult(status: Int, msg: String) {
if (0 == status) {
authinfo = "key校验成功!"
} else {
authinfo = "key校验失败, " + msg
}
activity.runOnUiThread({ Toast.makeText(activity, authinfo, Toast.LENGTH_LONG).show() })
}
override fun initSuccess() {
Toast.makeText(activity, "百度导航引擎初始化成功", Toast.LENGTH_SHORT).show()
isBaiduNaviInitSuccess = true
//设置语音导航
val bundle = Bundle()
// 必须设置APPID,否则会静音
bundle.putString(BNCommonSettingParam.TTS_APP_ID, BuildConfig.BaiduMapApiKey)
BNaviSettingManager.setNaviSdkParam(bundle)
BNaviSettingManager.setShowTotalRoadConditionBar(BNaviSettingManager.PreViewRoadCondition.ROAD_CONDITION_BAR_SHOW_ON)
BNaviSettingManager.setVoiceMode(BNaviSettingManager.VoiceMode.Veteran)
// BNaviSettingManager.setPowerSaveMode(BNaviSettingManager.PowerSaveMode.DISABLE_MODE);
BNaviSettingManager.setRealRoadCondition(BNaviSettingManager.RealRoadCondition.NAVI_ITS_ON)
BNaviSettingManager.setIsAutoQuitWhenArrived(true)
//开始百度导航
routePlanToNavi(startNaviName, endNaviName, naviLatLng)
DialogUtil.hide(loadingDialog)
}
override fun initStart() {
Toast.makeText(activity, "百度导航引擎初始化开始", Toast.LENGTH_SHORT).show()
}
override fun initFailed() {
isBaiduNaviInitSuccess = false
DialogUtil.hide(loadingDialog)
Toast.makeText(activity, "百度导航引擎初始化失败", Toast.LENGTH_SHORT).show()
}
}, null, TTSCallbackHandler(activity), TTSPlayStatusCallback(activity))
} else {
routePlanToNavi(startNaviName, endNaviName, naviLatLng)
DialogUtil.hide(loadingDialog)
}
}
/**
* 路线规划函数
* @param startNaviName 导航起始地
* @param endNaviName 导航目的地
*/
private fun routePlanToNavi(startNaviName: String, endNaviName: String, naviLatLng: Array<LatLng>) {
val sNode: BNRoutePlanNode = BNRoutePlanNode(naviLatLng[0].longitude, naviLatLng[0].latitude, startNaviName, null, BNRoutePlanNode.CoordinateType.BD09LL)
val eNode: BNRoutePlanNode = BNRoutePlanNode(naviLatLng[1].longitude, naviLatLng[1].latitude, endNaviName, null, BNRoutePlanNode.CoordinateType.BD09LL)
BaiduNaviManager.getInstance().launchNavigator(activity, arrayListOf(sNode, eNode), 1, true, BaiduRoutePlanListener(sNode), eventListerner)
}
/**
* 路线导航监听
* @param node 规划路线节点
*/
inner class BaiduRoutePlanListener(node: BNRoutePlanNode) : BaiduNaviManager.RoutePlanListener {
private var mBNRoutePlanNode: BNRoutePlanNode? = null
init {
mBNRoutePlanNode = node
}
override fun onJumpToNavigator() {
val intent = Intent(activity, BNGuideActivity::class.java)
val bundle = Bundle()
bundle.putSerializable(ROUTE_PLAN_NODE, mBNRoutePlanNode)
intent.putExtras(bundle)
activity.startActivity(intent)
}
override fun onRoutePlanFailed() {
Toast.makeText(activity, "路线规划失败", Toast.LENGTH_SHORT).show()
}
}
/**
* 语音播报播放状态回调
* @param activity 上下文对象
*/
class TTSPlayStatusCallback(val activity: Activity) : BaiduNaviManager.TTSPlayStateListener {
override fun playStart() {
Log.i(BaiduMapNavigator::class.java.simpleName, "status: 开始播报导航...")
}
override fun playEnd() {
Log.i(BaiduMapNavigator::class.java.simpleName, "status: 播报导航结束...")
}
}
/**
* 语音播报回调
* @param context 上下文对象
*/
class TTSCallbackHandler(val context: Context) : Handler() {
override fun handleMessage(msg: Message) {
val type = msg.what
when (type) {
BaiduNaviManager.TTSPlayMsgType.PLAY_START_MSG -> {
Log.i(BaiduMapNavigator::class.java.simpleName, "开始播报导航...")
}// showToastMsg("Handler : TTS play start");
BaiduNaviManager.TTSPlayMsgType.PLAY_END_MSG -> {
Log.i(BaiduMapNavigator::class.java.simpleName, "播报导航结束...")
}// showToastMsg("Handler : TTS play end");
else -> {
}
}
}
}
}
万事俱备只欠东风,那么该怎么调用呢?
java:
BaiduMapNavigator.getInstance(Activity activity).initNavigator(Context context, String startNaviName, String endNaviName, LatLng[] naviLatLng);
kotlin:
BaiduMapNavigator.getInstance(activity: Activity).initNavigator(context: Context, startNaviName: String, endNaviName: String, naviLatLng: Array<LatLng>);
功成身退,成败得失
集成第三方SDK其实并不麻烦,麻烦的是第三方提供的文档有时候是有误的或者表述并不明了,亦或者已经过时。这就很需要我们去查看Demo,归纳出我们自己需要的代码精华。集成这次百度导航中,最让我困惑的是arm64-v8a架构的设备找不到libgnustl_shared.so的位置,armeabi-v7a表现正常!