You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何获取谷歌地图蓝色定位点的平滑坐标以解决路径噪点问题

兄弟,我懂你遇到的问题——原始定位的噪点确实会把路径画得乱糟糟的。可惜的是,Google Maps Android SDK并没有开放获取内置蓝色定位点处理后坐标的接口,那个平滑逻辑是SDK内部私有的。不过别担心,我们有几个靠谱的替代方案,能让你的路径变得顺滑:

方案1:改用FusedLocationProviderClient获取更稳定的定位数据

原生LocationManager拿到的定位数据噪点多很正常,而Google官方的FusedLocationProviderClient整合了GPS、Wi-Fi、基站等多种定位源,内部已经做了一层平滑和过滤,能拿到更稳定的坐标。

你可以把原来的lokalizacja()方法替换成下面的实现:

private FusedLocationProviderClient fusedLocationClient;
private LocationCallback locationCallback;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // 保留你原来的初始化代码,新增FusedLocationClient初始化
    super.onCreate(savedInstanceState);
    // ... 其他代码
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}

public void lokalizacja() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        return;
    }

    // 配置定位请求参数,按需调整
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(1000); // 每秒更新一次
    locationRequest.setFastestInterval(500); // 最快500毫秒更新一次

    // 定义定位回调
    locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult == null || routeOpts == null) {
                return;
            }
            Location location = locationResult.getLastLocation();
            if (location != null) {
                LatLng myLatLng = new LatLng(location.getLatitude(), location.getLongitude());
                List<LatLng> points = route.getPoints();
                
                // 可选:过滤掉和上一个点距离过近的噪点(比如小于5米)
                if (points.size() > 0) {
                    LatLng lastPoint = points.get(points.size() - 1);
                    float[] distance = new float[1];
                    Location.distanceBetween(
                        lastPoint.latitude, lastPoint.longitude,
                        myLatLng.latitude, myLatLng.longitude,
                        distance
                    );
                    if (distance[0] >= 5) { // 只添加距离足够的点
                        points.add(myLatLng);
                        route.setPoints(points);
                    }
                } else {
                    points.add(myLatLng);
                    route.setPoints(points);
                }
            }
        }
    };

    // 开始请求定位更新
    fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
}

// 别忘了在页面销毁时停止定位,避免耗电
@Override
protected void onDestroy() {
    super.onDestroy();
    if (fusedLocationClient != null && locationCallback != null) {
        fusedLocationClient.removeLocationUpdates(locationCallback);
    }
}
方案2:自己实现平滑算法

如果觉得FusedLocation的结果还是不够顺滑,可以在拿到坐标后自己做二次处理,比如滑动平均算法(简单易实现)或者更复杂的卡尔曼滤波。这里给一个滑动平均的示例:

// 保存最近N个坐标点,用来计算平均值
private List<LatLng> recentPoints = new ArrayList<>();
private static final int SMOOTH_WINDOW_SIZE = 3; // 取最近3个点的平均

// 处理新坐标,生成平滑后的点
private void addSmoothedPoint(LatLng newPoint) {
    recentPoints.add(newPoint);
    // 保持窗口大小不超过设定值
    if (recentPoints.size() > SMOOTH_WINDOW_SIZE) {
        recentPoints.remove(0);
    }

    // 计算平均坐标
    double avgLat = 0, avgLng = 0;
    for (LatLng point : recentPoints) {
        avgLat += point.latitude;
        avgLng += point.longitude;
    }
    avgLat /= recentPoints.size();
    avgLng /= recentPoints.size();
    LatLng smoothedPoint = new LatLng(avgLat, avgLng);

    // 更新路径
    List<LatLng> points = route.getPoints();
    points.add(smoothedPoint);
    route.setPoints(points);
}

使用的时候,在onLocationResult里调用addSmoothedPoint(myLatLng),替代直接添加原始点即可。

额外注意事项
  • 确保你的项目依赖了Google Play Services定位库,在build.gradle里添加:
dependencies {
    // 替换成当前最新版本
    implementation 'com.google.android.gms:play-services-location:21.0.1'
}
  • 权限方面,除了ACCESS_FINE_LOCATION,也可以添加ACCESS_COARSE_LOCATION作为 fallback,在GPS信号弱的时候用网络定位。

内容的提问来源于stack exchange,提问作者Szymon Wołyniec

火山引擎 最新活动