使用 GPS 获取用户设备的精确位置

Get precise position of user device with GPS

在我的 Android 应用程序中,我需要使用汽车行驶的道路,并使用 google android 方向 API 和 GPS 检查它。

但问题是有时 GPS 位置不精确,我在某些讲座中可能会出现 10 公里的误差,这意味着在 150 公里的总行程中,我的 "distance traveled" 可能是 250 公里,这是错了!

昨天我在高速公路上测试了它,问题是当标记位于高速公路之外时,从我当前位置和最后一个标记在公路上的距离计算是非常错误的(在这种情况下高速公路)。

有一些使用 phone 获取汽车行驶距离的最佳方法吗? 也许有一些更好的代码来获得更精确的 GPS 位置? 这是我的代码:

private void getUserLocation() {

    Log.d(TAG, "getUserLocation()");
    checkLocationPermission();
    mFusedLocationClient.getLastLocation()
            .addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
                @Override
                public void onSuccess(Location location) {
                    // Got last known location. In some rare situations this can be null.
                    if (location != null) {
                        // Logic to handle location object
                        String stringStartLat, stringStartLng;

                        double lat = location.getLatitude();
                        double lng = location.getLongitude();

                        //Start position of device
                        if (travelInfo.getStartLat() == 0 && travelInfo.getStartLng() == 0) {
                            travelInfo.setStartLat(lat);
                            travelInfo.setStartLng(lng);
                            //Set lastcoordinates equals to start
                            travelInfo.setLastLat(lat);
                            travelInfo.setLastLng(lng);
                        }
                        //Current position of device
                        travelInfo.setCurrentLat(lat);
                        travelInfo.setCurrentLng(lng);

                        stringStartLat = Double.toString(travelInfo.getStartLat());
                        stringStartLng = Double.toString(travelInfo.getStartLng());
                        //Set the TextView in the fragment with start coordinates
                        Log.d(TAG,"LatitudeStart: " + stringStartLat);
                        Log.d(TAG,"LongitudeStart: " + stringStartLng);

                        if (startMarker == null) {
                            //Add the user location to the map with a marker
                            LatLng userLoction = new LatLng(travelInfo.getStartLat(), travelInfo.getStartLng());
                            startMarker = googleMap.addMarker(new MarkerOptions()
                                    .position(userLoction)
                                    .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
                                    .title("Start Position")
                                    .snippet("Show the start position of user"));

                            // For zooming automatically to the location of the marker
                            CameraPosition cameraPosition = new CameraPosition.Builder().target(userLoction).zoom(9).build();
                            googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
                        } else {

                            LatLng currentLocation = new LatLng(travelInfo.getCurrentLat(), travelInfo.getCurrentLng());
                            currentPositionMarker = googleMap.addMarker(new MarkerOptions()
                                    .position(currentLocation)
                                    .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW))
                                    .title("Current Position")
                                    .snippet("Show the current position of user during travel"));

                            // For zooming automatically to the location of the marker
                            CameraPosition cameraPosition = new CameraPosition.Builder().target(currentLocation).zoom(11).build();
                            googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
                        }

                        if (travelInfo.getEndLat() != 0 && travelInfo.getEndLng() != 0) {
                            Log.i(TAG, "Dentro if userlocation");
                            //Get total distance of travel
                            getTotalDistanceTime(travelInfo);
                            //Get the percurred distance from last known coordinates
                            getPercurredDistance(travelInfo);
                        }
                    }
                }
            });
}

并且 getpercurredDistance 使用 google 方向 API 与此 url

    String url = "https://maps.googleapis.com/maps/api/directions/json?origin=" + obj.getLastLat() + "," + obj.getLastLng() + "&destination=" + obj.getCurrentLat() + "," + obj.getCurrentLng() + "&mode=driving&key=AI*******************I";

用于获取从上一个标记到当前位置标记的行进距离。 但有时它会使本地化位置离实际位置太远...如何避免这种情况?

编辑

我使用的方法适合我的工作吗? mFusedLocationClient.getLastLocation()

无法从 android 设备的 GPS 传感器获得更精确的 GPS 位置,但您可以通过以下方式过滤 "wrong" 点:

1) 对每个行程点取LatLng的几个值,舍弃最小值和最大值,对剩余的取平均值;

2) 记录每个旅行点的时间戳并将其与两个相邻点进行比较:速度(两点之间的距离除以该点的时间间隔)大于最大值。汽车速度(例如 250 km/h),这意味着第二点是错误的(当然如果第一点是好的)。

3) 使用 Google Maps Roads API 为给定的一组 GPS 坐标找到最适合的道路几何形状。

另请参阅 this 问题。

为了实时定位,位置更新允许您以不同的时间间隔请求位置更新。参见android developer location documentation。你想要的函数是FusedLocationProviderClient.requestLocationUpdates

没有理由 GPS(或任何其他广泛使用的定位技术)应该给您 10 公里的单个位置估计误差。如果您收到此信息,则表明您进行位置估计的时间与您请求它的时间之间存在很大的不匹配。