Search code examples
androidsdknavigationmapbox

Im using mapbox sdk navigation v2 and have a problem with the cycling view


im trying to implement the cycling profile to the navigation, i did it this way:

    private fun requestRoutes(origin: Point, destination: Point) {
        MapboxNavigationApp.current()!!.requestRoutes(
            routeOptions = RouteOptions
                .builder()
                .applyDefaultNavigationOptions()
                .applyLanguageAndVoiceUnitOptions(this)
                .coordinatesList(listOf(origin, destination))
                .alternatives(true)
                .profile(DirectionsCriteria.PROFILE_CYCLING)
                .build(),
            callback = object : NavigationRouterCallback {
                override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) {
                    // no impl
                }

                override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
                    // no impl
                }

                override fun onRoutesReady(routes: List<NavigationRoute>, routerOrigin: RouterOrigin) {
                    binding.navigationView.api.startActiveGuidance(routes)
                    // binding.navigationView.api.routeReplayEnabled(true) simulate movement
                }
            }
        )
    }

here is my onCreate function:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // set the layout
        binding = MapboxActivityNavigationViewBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // get the arg of the js
        val routes = intent.getSerializableExtra("routes") as String
        val arrayList = JSONArray(routes);
        val originCoord = arrayList.getJSONObject(0)
        val destinationCoord = arrayList.getJSONObject(1)
        MapboxNavigationApp.current()?.registerLocationObserver(locationObserver)
        val origin = Point.fromLngLat(originCoord.getDouble("longitude"), originCoord.getDouble("latitude"))
        val destination = Point.fromLngLat(destinationCoord.getDouble("longitude"), destinationCoord.getDouble("latitude"))
        origing = origin
        destinationg = destination

        // set the custom view binder
        val navigationActivity = this
        findViewById<NavigationView>(R.id.navigationView).customizeViewBinders {
            infoPanelEndNavigationButtonBinder = MyinfoPanelEndNavigationButtonBinder(navigationActivity)
        }

        // launch the active guidance
        requestRoutes(origin, destination)
    }

Unfortunately when setting the profile to cycling the navigation doesnt start and it stays in free-drive mode, in other profile (driving, walking) everything works fine, is that a bug of the sdk or am i doing something wrong ?

I couldn't find any help in the documentation or on the internet


Solution

  • I figured it out guys, in my requestRoutes function, i have those route options.

    routeOptions = RouteOptions
                    .builder()
                    .applyDefaultNavigationOptions()
                    .applyLanguageAndVoiceUnitOptions(this)
                    .coordinatesList(listOf(origin, destination))
                    .alternatives(true)
                    .profile(DirectionsCriteria.PROFILE_CYCLING)
                    .build(),
    

    turns out that the applyDefaultNavigationOptions() is implemented this way:

    fun RouteOptions.Builder.applyDefaultNavigationOptions(
        @DirectionsCriteria.ProfileCriteria profile: String =
            DirectionsCriteria.PROFILE_DRIVING_TRAFFIC
    ): RouteOptions.Builder = apply {
        val defaultAnnotations = listOf(
            DirectionsCriteria.ANNOTATION_SPEED,
            DirectionsCriteria.ANNOTATION_DURATION,
            DirectionsCriteria.ANNOTATION_DISTANCE,
        )
    
        when (profile) {
            DirectionsCriteria.PROFILE_DRIVING_TRAFFIC -> {
                annotationsList(
                    mutableListOf(
                        DirectionsCriteria.ANNOTATION_CONGESTION_NUMERIC,
                        DirectionsCriteria.ANNOTATION_MAXSPEED,
                        DirectionsCriteria.ANNOTATION_CLOSURE,
                    ).apply { addAll(defaultAnnotations) }
                )
                continueStraight(true)
                enableRefresh(true)
            }
            DirectionsCriteria.PROFILE_DRIVING -> {
                annotationsList(
                    mutableListOf(
                        DirectionsCriteria.ANNOTATION_MAXSPEED,
                    ).apply { addAll(defaultAnnotations) }
                )
                continueStraight(true)
                enableRefresh(false)
            }
            DirectionsCriteria.PROFILE_CYCLING,
            DirectionsCriteria.PROFILE_WALKING -> {
                annotationsList(defaultAnnotations)
                continueStraight(false)
                enableRefresh(false)
            }
            else -> throw IllegalArgumentException(
                "Unknown profile [$profile]. It must be one [DirectionsCriteria.ProfileCriteria]"
            )
        }
    

    So i was overriding the profile since it was already set in this function. No idea why the overriding of the profile wasn't a problem for the walking and driving profile but not the cycling one but you can fix this issue by just passing the profile in the applyDefaultNavigationOptions() function as so:

    routeOptions = RouteOptions
                    .builder()
                    .applyDefaultNavigationOptions(DirectionsCriteria.PROFILE_CYCLING)
                    .applyLanguageAndVoiceUnitOptions(this)
                    .coordinatesList(listOf(origin, destination))
                    .alternatives(true)
                    .build(),