如何借助FusedLocationProviderClient获取精准的经纬度定位
Hey, I’ve run into this exact location jump problem with FusedLocationProviderClient before—those sudden spikes from 10m to 200m (and right back) are almost always caused by switching between low-accuracy network positioning and GPS, or noisy, drifted location readings. Let’s walk through practical fixes tailored to your code:
1. Filter out low-accuracy location readings
The Location object returned by FusedLocationProvider includes an accuracy field (in meters) that tells you how reliable the reading is. You can set a threshold to ignore any readings that are too imprecise—for example, only keep locations with an error margin of 20 meters or less:
Update your onNewLocation method to add this check:
private fun onNewLocation(location: Location) { Log.i(TAG, "New location: $location") // Skip readings that are too inaccurate if (location.accuracy > 20) { Log.w(TAG, "Ignoring low-accuracy location (${location.accuracy}m error)") return } mLocation = location // Your existing distance calculation logic here... }
2. Tweak your LocationRequest parameters
You’re already using PRIORITY_HIGH_ACCURACY (great call!), but we can add a couple more settings to reduce jumps:
- Add
smallestDisplacement: This tells the provider only to send updates when the user moves beyond a certain distance, which filters out tiny drift-induced updates. - Adjust interval timing if you don’t need 5-second updates—longer intervals give the GPS module time to lock onto a stable signal.
Modify your createLocationRequest function:
private fun createLocationRequest() { mLocationRequest = LocationRequest() mLocationRequest!!.interval = UPDATE_INTERVAL_IN_MILLISECONDS // You could bump this to 10000 (10s) if you don't need frequent updates mLocationRequest!!.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY // Only trigger updates if the user moves 5+ meters mLocationRequest!!.smallestDisplacement = 5f }
3. Add location smoothing with a simple cache
For occasional rogue jump readings, you can smooth your location data by averaging the last few valid points. This softens sudden spikes:
First, add a cache to your LocServices class:
private val validLocations = mutableListOf<Location>() private const val MAX_CACHED_LOCATIONS = 3 // Keep last 3 valid readings
Then update onNewLocation to use this cache:
private fun onNewLocation(location: Location) { if (location.accuracy > 20) { Log.w(TAG, "Ignoring low-accuracy location (${location.accuracy}m error)") return } // Update the cache, keeping only the last 3 valid locations validLocations.add(location) if (validLocations.size > MAX_CACHED_LOCATIONS) { validLocations.removeAt(0) } // Calculate the average of cached locations for a smoothed reading val avgLat = validLocations.map { it.latitude }.average() val avgLng = validLocations.map { it.longitude }.average() val smoothedLocation = Location("smoothed").apply { latitude = avgLat longitude = avgLng accuracy = validLocations.map { it.accuracy }.average().toFloat() } mLocation = smoothedLocation // Use smoothedLocation for your distance calculation instead of raw location val selected_location = Location("locationA") selected_location.latitude = existLatitude!!.toDouble() selected_location.longitude = existLongitude!!.toDouble() val distance = selected_location.distanceTo(smoothedLocation) // Rest of your toast logic here... }
4. Validate the "last location" before using it
Your getLastLocation call might return an old or inaccurate reading. Add checks to ensure it’s recent and precise enough:
private fun getLastLocation() { try { mFusedLocationClient!!.lastLocation .addOnCompleteListener { task -> if (task.isSuccessful && task.result != null) { val lastLoc = task.result // Only accept locations from the last 5 minutes with good accuracy val fiveMinutesAgo = System.currentTimeMillis() - 5 * 60 * 1000 if (lastLoc.time > fiveMinutesAgo && lastLoc.accuracy <= 20) { mLocation = lastLoc } else { Log.w(TAG, "Ignoring outdated or low-accuracy last location") } } else { Log.w(TAG, "Failed to get location.") } } } catch (unlikely: SecurityException) { Log.e(TAG, "Lost location permission.$unlikely") } }
5. Ensure proper permissions and device settings
- Double-check that you’re requesting
ACCESS_FINE_LOCATION(not justACCESS_COARSE_LOCATION) in your manifest and runtime permissions—high-accuracy GPS requires this. - Prompt users to enable High Accuracy mode in their device settings (this combines GPS, Wi-Fi, and cellular data for more stable readings).
These changes should drastically reduce those frustrating distance spikes and give your users a more reliable experience.
内容的提问来源于stack exchange,提问作者J. Shiv

