一、简单使用示例
1. 初始化 MapboxNavigation
初始化时使用 NavigationOptions 设置一些参数,包括accessToken、appMetaData、LocationEngine等,其它还有很多,具体可以详看 NavigationOptions 类的内部。
下面示例中 LocationEngine 使用的重演定位引擎,可以看到模拟导航的效果,关键的两个类就是 ReplayLocationEngine 和 MapboxReplayer 。
/* ----- Mapbox Navigation components ----- */
private lateinit var mapboxNavigation: MapboxNavigationprivate val mapboxReplayer = MapboxReplayer()// initialize Mapbox Navigation
mapboxNavigation = MapboxNavigationProvider.create(NavigationOptions.Builder(applicationContext).accessToken(getMapboxAccessTokenFromResources()).eventsAppMetadata(EventsAppMetadata.Builder(BuildConfig.APPLICATION_ID,BuildConfig.VERSION_NAME).build()).locationEngine(ReplayLocationEngine(mapboxReplayer)).build()
)
2. 初始化 LocationObserver,对位置改变做观察
navigationLocationProvider 只是把当前导航的位置点给到 MapView,实现地图移动或者加位置图标等。
MapboxNavigationViewportDataSource 也是一样,移动地图的Camera到一个合适的位置,要结合 NavigationCamera 使用。NavigationCamera 还可以改变导航是 Following 还是 Overview 。
// camera
private lateinit var navigationCamera: NavigationCamera
private lateinit var viewportDataSource: MapboxNavigationViewportDataSource// initialize Navigation Camera
viewportDataSource = MapboxNavigationViewportDataSource(binding.mapView.getMapboxMap()
)
navigationCamera = NavigationCamera(binding.mapView.getMapboxMap(),binding.mapView.camera,viewportDataSource
)/* ----- Location and route progress callbacks ----- */
private val locationObserver = object : LocationObserver {override fun onNewRawLocation(rawLocation: Location) {// not handled}override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {// update location puck's position on the mapnavigationLocationProvider.changePosition(location = locationMatcherResult.enhancedLocation,keyPoints = locationMatcherResult.keyPoints,)// update camera position to account for new locationviewportDataSource.onLocationChanged(locationMatcherResult.enhancedLocation)viewportDataSource.evaluate()}
}
3. 初始化 RoutesObserver,对多条路线的处理
private val routesObserver = RoutesObserver { result ->if (result.routes.isNotEmpty()) {// generate route geometries asynchronously and render themCoroutineScope(Dispatchers.Main).launch {val result = routeLineAPI.setRoutes(listOf(RouteLine(result.routes.first(), null)))val style = mapboxMap.getStyle()if (style != null) {routeLineView.renderRouteDrawData(style, result)}}// update the camera position to account for the new routeviewportDataSource.onRouteChanged(result.routes.first())viewportDataSource.evaluate()} else {// remove the route line and route arrow from the mapval style = mapboxMap.getStyle()if (style != null) {routeLineAPI.clearRouteLine { value ->routeLineView.renderClearRouteLineValue(style,value)}routeArrowView.render(style, routeArrowAPI.clearArrows())}// remove the route reference to change camera positionviewportDataSource.clearRouteData()viewportDataSource.evaluate()}
}
4. 初始化 NavigationSessionStateObserver ,对导航状态的监测
private val navigationSessionStateObserver = NavigationSessionStateObserver {logD("NavigationSessionState=$it", LOG_CATEGORY)logD("sessionId=${mapboxNavigation.getNavigationSessionState().sessionId}", LOG_CATEGORY)
}
5. 初始化 RouteProgressObserver ,对导航进度
的监测
最关键的部分,如下是正常导航时的进度处理。但是对于模拟导航,只需要实例化 ReplayProgressObserver 对象。
// 模拟导航使用
private val routeProgressObserver1 = ReplayProgressObserver(mapboxReplayer)// 正常导航使用private val routeProgressObserver =RouteProgressObserver { routeProgress ->// update the camera position to account for the progressed fragment of the routeviewportDataSource.onRouteProgressChanged(routeProgress)viewportDataSource.evaluate()// show arrow on the route line with the next maneuverval maneuverArrowResult = routeArrowAPI.addUpcomingManeuverArrow(routeProgress)val style = mapboxMap.getStyle()if (style != null) {routeArrowView.renderManeuverUpdate(style, maneuverArrowResult)}// update top maneuver instructionsval maneuvers = maneuverApi.getManeuvers(routeProgress)maneuvers.fold({ error ->Toast.makeText(this@MapboxNavigationActivity,error.errorMessage,Toast.LENGTH_SHORT).show()},{binding.maneuverView.visibility = VISIBLEbinding.maneuverView.renderManeuvers(maneuvers)})// update bottom trip progress summarybinding.tripProgressView.render(tripProgressApi.getTripProgress(routeProgress))}
6. 初始化 VoiceInstructionsObserver ,对语音指令的监测
// 语音播报对象
private lateinit var voiceInstructionsPlayer: MapboxVoiceInstructionsPlayervoiceInstructionsPlayer = MapboxVoiceInstructionsPlayer(this,Locale.US.language
)// 静音和取消静音
voiceInstructionsPlayer.volume(SpeechVolume(0f))
voiceInstructionsPlayer.volume(SpeechVolume(1f))/* ----- Voice instruction callbacks ----- */
private val voiceInstructionsObserver =VoiceInstructionsObserver { voiceInstructions ->speechAPI.generate(voiceInstructions,speechCallback)}// speechCallback 中做 play
private val speechCallback =MapboxNavigationConsumer<Expected<SpeechError, SpeechValue>> { expected ->expected.fold({ error ->// play the instruction via fallback text-to-speech enginevoiceInstructionsPlayer.play(error.fallback,voiceInstructionsPlayerCallback)},{ value ->// play the sound file from the external generatorvoiceInstructionsPlayer.play(value.announcement,voiceInstructionsPlayerCallback)})}
7. findRoute并将路线设置给导航模块,然后开启导航
// findRoute
mapboxNavigation.requestRoutes()// 路线获取成功 onRoutesReady 后的处理
private fun setRouteAndStartNavigation(route: List<NavigationRoute>) {// set routemapboxNavigation.setNavigationRoutes(route)// show UI elementsbinding.soundButton.visibility = VISIBLEbinding.routeOverview.visibility = VISIBLEbinding.tripProgressCard.visibility = VISIBLEbinding.routeOverview.showTextAndExtend(2000L)binding.soundButton.unmuteAndExtend(2000L)// move the camera to overview when new route is availablenavigationCamera.requestNavigationCameraToOverview()
}override fun onStart() {super.onStart()mapboxNavigation.registerRoutesObserver(routesObserver)mapboxNavigation.registerNavigationSessionStateObserver(navigationSessionStateObserver)
// mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)mapboxNavigation.registerRouteProgressObserver(routeProgressObserver1)mapboxNavigation.registerLocationObserver(locationObserver)mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver)// 实际导航只需要注册好上面的观察者,下面时模拟导航的特殊开启方式mapboxReplayer.pushRealLocation(this, 0.0)mapboxReplayer.playbackSpeed(1.5)mapboxReplayer.play()
}
二、关键类
类名 | 所属模块 | 作用 |
---|---|---|
MapboxNavigation | libnavigation-core | 核心类,要给它配置token,定位引擎等。 mapboxNavigation.startTripSession() registerLocationObserver() 观察位置变化。 registerRoutesObserver() 对导航路线的处理,比如渲染,箭头等。 registerNavigationSessionStateObserver() registerRouteProgressObserver() 导航进度。 registerVoiceInstructionsObserver() 语音指令。 |
NavigationOptions | libnavigation-base | 给 MapboxNavigation 配置token,定位引擎等使用此对象。 还有很多其它的配置项。 |
RoutesObserver | libnavigation-core | 对导航路线改变时,在这个接口方法中实现渲染。 |
RouteProgressObserver | libnavigation-core | 提供状态、进度和其他有关当前逐点路由的信息的回调。 |
LocationObserver | libnavigation-core | 监听位置更新。 |
VoiceInstructionsObserver | libnavigation-core | 语音指令接口。 |
----------------------------- | ----------------------------- | ----------------------------- |
MapboxNavigationViewportDataSource | libnavui-maps | UI相关,需要把 MapView 对象传递给此类。 |
NavigationCamera | libnavui-maps | UI相关,需要把 MapView,camera,MapboxNavigationViewportDataSource 对象传递给此类。 |
NavigationBasicGesturesHandler | libnavui-maps | UI相关,基础手势。 |
MapboxManeuverApi | libnavui-maneuver | UI相关,顶部显示还有多少米向左向右转等信息。 |
MapboxTripProgressApi | libnavui-tripprogress | UI相关,底部进度,剩余时间,剩余距离,当前时间。 |
MapboxSpeechApi | libnavui-voice | UI相关,语音部分。 |
MapboxVoiceInstructionsPlayer | libnavui-voice | UI相关,语音部分。 |
MapboxRouteLineApi | libnavui-maps | UI相关,路线上图相关。 |
MapboxRouteLineView | libnavui-maps | UI相关,路线上图相关。 |
MapboxRouteArrowView | libnavui-maps | UI相关,路线上图相关。 |
----------------------------- | ----------------------------- | ----------------------------- |
ReplayLocationEngine | libnavigation-core | 模拟导航相关类,要在NavigationOptions设置这种定位引擎 |
MapboxReplayer | libnavigation-core | 模拟导航相关类,控制模拟导航play,finish等 |
ReplayRouteMapper | libnavigation-core | 模拟导航相关类,利用它里面的方法把要模拟的路线对象DirectionsRoute设置进去 |
ReplayProgressObserver | libnavigation-core | 模拟导航相关类,观察模拟导航的进度,替代正常导航进度观察RouteProgressObserver |
三、NavigationView
布局文件 mapbox_navigation_view_layout.xml
init { } 方法块中会创建MapView并添加到布局,利用mapLayoutCoordinator(binding)
实例化 MapLayoutCoordinator
。
再利用 MapLayoutCoordinator
里的方法给 core 模块中的 MapboxNavigation
绑定 MapView。
MapView 的创建使用 MapViewBinder
,而对它设置样式使用 MapStyleLoader
。
四、获取导航路线 requestRoutes() 详细
是 MapboxNavigation
中获取导航路线的方法,有两个方法,参数有差异
fun requestRoutes(routeOptions: RouteOptions,routesRequestCallback: RouterCallback
)fun requestRoutes(routeOptions: RouteOptions,callback: NavigationRouterCallback
)
RouterCallback
中获取导航路线成功得到的是 DirectionsRoute
集合,在模拟导航中使用 DirectionsRoute
对象。也对应结合 MapboxNavigation.setRoutes(List<DirectionsRoute>)
使用,方法内部会利用 toNavigationRoutes()
做转换。
NavigationRouterCallback
中获取导航路线成功得到的是 NavigationRoute
集合,对应结合 MapboxNavigation.setNavigationRoutes(List<NavigationRoute>)
使用。
toNavigationRoutes()
是把 DirectionsRoute
集合转为 NavigationRoute
集合,也有 toDirectionsRoutes()
可以把 NavigationRoute
集合转为 DirectionsRoute
集合。