2

I'm working in a project that need to show a NavigationView inside a fragment. It's working fine but consume a lot of battery (and depending of the device in some increase temperature considerably). I checked the profiler in AS to try to identify the issue,

let's see...

profiler capture

As I can understand, Mapbox Navigation ask for location in High Accuracy every one second. The question is, there is any way to configure the priority or the interval to reduce battery comsumption?

I followed the official docs to implement a custom LocationEngine, and works right for MapView, but not for NavigationView.

Anyone had this kind of issues in terms of performance with Mapbox Navigation? I've already test it in new and old devices and it's the same every time.

I'm using:

implementation "com.mapbox.navigation:ui:1.4.0"
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.6.0'

And here are some part of my implementation,

private fun initLocationEngine() {
    locationEngine = LocationEngineProvider.getBestLocationEngine(requireContext())
    // i don't know if is necessary to remove location updates before configure a new location engine
    locationEngine?.removeLocationUpdates(this)
    val request =
        LocationEngineRequest.Builder(30000)
            .setPriority(LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY)
            .setMaxWaitTime(10000).build()
    

    locationEngine?.requestLocationUpdates(request, this, getMainLooper())
}

override fun onMapReady(mapboxMap: MapboxMap) {
    mapView = mapboxMap
    mapView.setStyle(Style.TRAFFIC_DAY) {
            initLocationEngine()
            initCamera(mapboxMap)
    }
}

private fun setupNavigationOptions(directionsRoute: DirectionsRoute): NavigationViewOptions {
    val options = NavigationViewOptions.builder(requireContext())

    options.directionsRoute(directionsRoute)
        .navigationListener(this)
        .feedbackListener(this)
        .locationObserver(this)
        .locationEngine(locationEngine)
    return options.build()
}

private fun getNavigationRoute(origin: Point, destination: Point) {
    val navigation = MapboxNavigation.defaultNavigationOptionsBuilder(getCurrentContext(), Mapbox.getAccessToken())
    mapboxNavigation = MapboxNavigation(navigation.build())
    
    val routeOptions = RouteOptions.builder()
        .applyDefaultParams()
        .accessToken(Mapbox.getAccessToken()!!)
        .coordinates(coordinates)
        .geometries(RouteUrl.GEOMETRY_POLYLINE6)
        .profile(DirectionsCriteria.PROFILE_DRIVING)
        .alternatives(false)
        .voiceUnits(DirectionsCriteria.METRIC)
        .build()

    mapboxNavigation.requestRoutes(routeOptions, object : RoutesRequestCallback {
        override fun onRoutesReady(routes: List<DirectionsRoute>) {
            if (routes.isNotEmpty() && isAdded) {
                val currentRoute = routes.first()
                navigationView.startNavigation(setupNavigationOptions(currentRoute))
                showNavigationMode()
            }
        }

        override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {
            Timber.e("route request failure %s", throwable.toString())
        }

        override fun onRoutesRequestCanceled(routeOptions: RouteOptions) {
            Timber.d("route request canceled")
        }
    })
}

// these methods are from LocationObserver callback
override fun onEnhancedLocationChanged(enhancedLocation: Location, keyPoints: List<Location>) {
   // this method called every second, so, LocationEngine it's configured fine but the criteria and interval configuration does'nt work
}

override fun onRawLocationChanged(rawLocation: Location) {
   
}

// EDIT After Yoshikage Ochi comment I made some changes to my setupNavigationOptions method:

private fun setupNavigationOptions(directionsRoute: DirectionsRoute): NavigationViewOptions {
       
   val navViewOptions = NavigationViewOptions.builder(requireContext())
        
   val navOpt = MapboxNavigation.defaultNavigationOptionsBuilder(requireContext(), Mapbox.getAccessToken())
    val request =
        LocationEngineRequest.Builder(30000)              
.setPriority(LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY).build()

    navOpt.locationEngineRequest(request)
    navViewOptions.navigationOptions(navOpt.build())

    navViewOptions.directionsRoute(directionsRoute)
        .navigationListener(this)
        .feedbackListener(this)
        .locationObserver(this)
    return options.build()
    }

But unfortunatly it does'nt work. The period and the priority is the same (maybe the default), I've receiving updates every second and in HIGH_PRIORITY.

Fer Juarez
  • 55
  • 1
  • 5

1 Answers1

2

In your implementation, your setting will be overwritten by the default setting when the trip session starts as Google doc explains.

NavigationOptions has an option named locationEngineRequest that is used to configure LocationEngine (example).

Following code demonstrates how NavigationOptions can be used in NavigationViewOptions that is a parameter of NavigationView#startNavigation

val optionsBuilder = NavigationViewOptions.builder(this@MainActivity)
optionsBuilder.navigationOptions(MapboxNavigation
    .defaultNavigationOptionsBuilder(this@MainActivity, Mapbox.getAccessToken())
        .locationEngineRequest(LocationEngineRequest.Builder(5)
        .build())
    .build())

In the meantime, the location update energy consumption is way smaller than CPU energy consumption according to your performance result.

In this case, how about using FPS throttle mechanism that would reduce CPU power consumption? This setting clips the max FPS when the device is running on battery and meets some conditions. The default value is 20.

navigationView.retrieveNavigationMapboxMap()?.updateMapFpsThrottle(5);
Yoshikage Ochi
  • 226
  • 2
  • 4
  • Thanks for the info! I´m going to test it and update the answer. – Fer Juarez Feb 16 '21 at 16:09
  • I edited the question, it does'nt work :( – Fer Juarez Feb 24 '21 at 16:26
  • >The period and the priority is the same (maybe the default), I've receiving updates every second and in HIGH_PRIORITY. How did you check this? If you check Profiler, you might see the activity of telemetry that uses different [FusedLocationProvider](https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient#public-taskvoid-requestlocationupdates-locationrequest-request,-pendingintent-callbackintent) In this meaning, reducing the number of request does not impact power usage a lot. – Yoshikage Ochi Feb 26 '21 at 16:04