-
Notifications
You must be signed in to change notification settings - Fork 151
Description
Environment
- Android OS version: 16
- Devices affected: Pixel 9, Samsung S25
- Maps SDK Version: Unsure -- I reproduced using the latest mapbox-maps-android commit on the main branch
Observed behavior and steps to reproduce
When using a custom LocationProvider
, any LocationComponentPlugin
settings are changed before setting the custom provider, there is a LocationRequest
left open from the DefaultLocationProvider
that prevents batching LocationRequests
. This impacts all other LocationRequests
in the app that might otherwise be able to batch. This request remains open when the app is backgrounded or when the phone is locked as well, resulting in significant battery consumption. If the custom LocationProvider
is set BEFORE updating any other LocationComponentPlugin
settings, the DefaultLocationProvider
is never instantiated and therefore this LocationRequest
is never registered with the OS, allowing the consumer app's batching LocationRequest
s to behave as expected.
The necessity to register a custom LocationProvider
before changing any other settings is neither expected nor documented.
Expected behavior
It should not matter at what point I set my custom LocationProvider
-- once it is set, the default LocationRequest
should be removed so that my LocationRequest
s can be batched as I intend.
Notes / preliminary analysis
From the sample app's LocationTrackingActivity
:
private fun initLocationComponent() {
val locationComponentPlugin = mapView.location
/**********
* Setting location provider here is safe, because it when updateSettings is called, the location provider
* is not null, so we never instantiate a DefaultLocationProvider
*/
locationComponentPlugin.setLocationProvider(FakeLocationProvider())
locationComponentPlugin.updateSettings {
puckBearing = PuckBearing.COURSE
puckBearingEnabled = true
enabled = true
locationPuck = LocationPuck2D(
bearingImage = ImageHolder.from(R.drawable.mapbox_user_puck_icon),
shadowImage = ImageHolder.from(R.drawable.mapbox_user_icon_shadow),
scaleExpression = interpolate {
linear()
zoom()
stop {
literal(0.0)
literal(0.6)
}
stop {
literal(20.0)
literal(1.0)
}
}.toJson()
)
}
/**********
* Setting the location provider here is NOT SAFE. At this point, since it was null when updateSettings
* was called, we created a DefaultLocationProvider. DefaultLocationProvider somehow registers a LocationRequest
* that has a `minUpdateDistance` of 0.1 meters. This is a non-batching LocationRequest, and doesn't get
* removed when setting a custom provider OR WHEN BACKGROUNDING THE APP.
*/
// locationComponentPlugin.setLocationProvider(FakeLocationProvider())
locationComponentPlugin.addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)
locationComponentPlugin.addOnIndicatorBearingChangedListener(onIndicatorBearingChangedListener)
}
Additional links and references
The following logs were gathered via adb shell dumpsys activity service com.google.android.location.internal.GoogleLocationManagerService
. They show the open request with minUpdateDistance=0.1
when the custom LocationProvider
is set after updating the other settings, and it is missing when set before updating the other settings.
DefaultLocationProvider
(no custom provider):
Fused Location Provider:
source: Request[@1s HIGH_ACCURACY, WorkSource{10310 com.mapbox.maps.testapp}]
listeners:
10185/com.google.android.gms[fused_location_provider]/179714e4 (FINE) Request[PASSIVE, minUpdateInterval=0s, maxUpdateAge=0s, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[current_semantic_location]/db8f52de (FINE) Request[@2m(10m)/10m BALANCED_POWER_ACCURACY, minUpdateInterval=15s, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
10310/com.mapbox.maps.testapp/6854d070 (FINE) Request[@1s HIGH_ACCURACY, minUpdateDistance=0.1, waitForAccurateLocation, WorkSource{10310 com.mapbox.maps.testapp}]
1000/android[LocationService]/74484423 (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=0s, THROTTLE_NEVER, bypass, WorkSource{1000 android}]
10310/com.mapbox.maps.testapp/70197718 (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=1s, minUpdateDistance=1.0, maxUpdateAge=2s, waitForAccurateLocation, WorkSource{10310 com.mapbox.maps.testapp}]
10185/com.google.android.gms[.findmydevice]/a462af5d (FINE) Request[@20m BALANCED_POWER_ACCURACY, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
10304/com.alltrails.alltrailsalpha/e2a18811 {bg, na} (FINE) Request[PASSIVE/4s, minUpdateInterval=1s, minUpdateDistance=1.0, maxUpdateAge=2s, waitForAccurateLocation, WorkSource{10304 com.alltrails.alltrailsalpha}] (inactive)
10185/com.google.android.gms[earthquake_alerting]/d8b1b22f (FINE) Request[@30m BALANCED_POWER_ACCURACY, minUpdateInterval=5m, minUpdateDistance=1000.0, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[.personalsafety]/4a589c94 (FINE) Request[@10m BALANCED_POWER_ACCURACY, minUpdateInterval=2m, minUpdateDistance=40.0, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[fused_location_provider]/b03aa68d (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=750ms, maxUpdateAge=1h, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
Custom provider, added after updateSettings
:
Fused Location Provider:
source: Request[@1s HIGH_ACCURACY, WorkSource{10310 com.mapbox.maps.testapp}]
listeners:
10185/com.google.android.gms[fused_location_provider]/179714e4 (FINE) Request[PASSIVE, minUpdateInterval=0s, maxUpdateAge=0s, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[current_semantic_location]/db8f52de (FINE) Request[@2m(10m)/10m BALANCED_POWER_ACCURACY, minUpdateInterval=15s, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
10310/com.mapbox.maps.testapp/fafaa085 (FINE) Request[@1s HIGH_ACCURACY, minUpdateDistance=0.1, waitForAccurateLocation, WorkSource{10310 com.mapbox.maps.testapp}]
1000/android[LocationService]/74484423 (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=0s, THROTTLE_NEVER, bypass, WorkSource{1000 android}]
10185/com.google.android.gms[.findmydevice]/a462af5d (FINE) Request[@20m BALANCED_POWER_ACCURACY, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
10310/com.mapbox.maps.testapp/e74080d9 (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=1s, minUpdateDistance=1.0, maxUpdateAge=2s, waitForAccurateLocation, WorkSource{10310 com.mapbox.maps.testapp}]
10304/com.alltrails.alltrailsalpha/e2a18811 {bg, na} (FINE) Request[PASSIVE/4s, minUpdateInterval=1s, minUpdateDistance=1.0, maxUpdateAge=2s, waitForAccurateLocation, WorkSource{10304 com.alltrails.alltrailsalpha}] (inactive)
10185/com.google.android.gms[earthquake_alerting]/d8b1b22f (FINE) Request[@30m BALANCED_POWER_ACCURACY, minUpdateInterval=5m, minUpdateDistance=1000.0, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[.personalsafety]/4a589c94 (FINE) Request[@10m BALANCED_POWER_ACCURACY, minUpdateInterval=2m, minUpdateDistance=40.0, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[fused_location_provider]/b03aa68d (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=750ms, maxUpdateAge=1h, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
Custom provider, added before updateSettings
:
Fused Location Provider:
source: Request[@2m(10m)/10m BALANCED_POWER_ACCURACY, WorkSource{10185 com.google.android.gms}]
listeners:
10310/com.mapbox.maps.testapp/f88cc222 (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=1s, minUpdateDistance=1.0, maxUpdateAge=2s, waitForAccurateLocation, WorkSource{10310 com.mapbox.maps.testapp}]
10185/com.google.android.gms[current_semantic_location]/db8f52de (FINE) Request[@2m(10m)/10m BALANCED_POWER_ACCURACY, minUpdateInterval=15s, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
1000/android[LocationService]/74484423 (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=0s, THROTTLE_NEVER, bypass, WorkSource{1000 android}]
10185/com.google.android.gms[.findmydevice]/a462af5d (FINE) Request[@20m BALANCED_POWER_ACCURACY, THROTTLE_ALWAYS, WorkSource{10185 com.google.android.gms}]
10304/com.alltrails.alltrailsalpha/e2a18811 {bg, na} (FINE) Request[PASSIVE/4s, minUpdateInterval=1s, minUpdateDistance=1.0, maxUpdateAge=2s, waitForAccurateLocation, WorkSource{10304 com.alltrails.alltrailsalpha}] (inactive)
10185/com.google.android.gms[earthquake_alerting]/d8b1b22f (FINE) Request[@30m BALANCED_POWER_ACCURACY, minUpdateInterval=5m, minUpdateDistance=1000.0, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[.personalsafety]/4a589c94 (FINE) Request[@10m BALANCED_POWER_ACCURACY, minUpdateInterval=2m, minUpdateDistance=40.0, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]
10185/com.google.android.gms[fused_location_provider]/b03aa68d (FINE) Request[PASSIVE/106751991167d7h12m55s807ms, minUpdateInterval=750ms, maxUpdateAge=1h, THROTTLE_NEVER, WorkSource{10185 com.google.android.gms}]