优化 Android 中 Mapbox Navigation SDK 的电池使用

问题描述

我正在处理一个需要在片段中显示 NavigationView 的项目。它工作正常,但会消耗大量电池(并且取决于设备,温度会显着升高)。 我检查了 AS 中的分析器以尝试找出问题,

让我们看看...

profiler capture

据我所知,MapBox Navigation 每隔一秒就要求高精度的位置。 问题是,有没有什么办法可以配置优先级或间隔来减少电池消耗?

我按照 official docs 实现自定义 LocationEngine,适用于 MapView,但不适用于 NavigationView。

有人在 MapBox Navigation 的性能方面遇到过这种问题吗?我已经在新旧设备上测试过了,每次都一样。

我正在使用:

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

这是我实现的一部分,

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) {
   
}

// 编辑 在 Yoshikage Ochi 发表评论后,我对 setupNavigationoptions 方法进行了一些更改:

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()
    }

但不幸的是它不起作用。周期和优先级是相同的(可能是认值),我每秒都会收到更新,并且在 HIGH_PRIORITY 中。

解决方法

在您的实现中,当行程会话以 Google doc explains 开始时,您的设置将被默认设置覆盖。

NavigationOptions 有一个名为 locationEngineRequest 的选项,用于配置 LocationEngine (example)。

以下代码演示了如何在作为 NavigationOptions 参数的 NavigationViewOptions 中使用 NavigationView#startNavigation

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

同时,根据您的性能结果,位置更新能耗远小于 CPU 能耗。

在这种情况下,如何使用 FPS 节流机制来降低 CPU 功耗?当设备 is running on battery and meets some conditions 时,此设置会限制最大 FPS。默认值为 20

navigationView.retrieveNavigationMapboxMap()?.updateMapFpsThrottle(5);