You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现当前坐标在目标坐标10米半径内的校验?现有代码仅判断1公里

10米半径坐标校验的代码问题及修正方案

我需要判断当前设备坐标是否在目标坐标的10米范围内,自己写了一段代码但不确定可靠性。现在发现代码里只做了1公里范围的判断,不知道怎么改成10米的校验,也不清楚代码有没有其他潜在问题。原代码如下:

punchin.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        punchout.setVisibility(View.VISIBLE);
        punchin.setVisibility(View.INVISIBLE);
        curLocation.setText("");
        tarLocation.setText("");
        String androidID = getIMEINumber();

        if (androidID != null) {
            getCurrentLocation();
            // Execute the Api's

            double targetLatitude = 19.2185561;// Specify the latitude of the target location
            double targetLongitude = 72.86228096;// Specify the longitude of the target location

            float[] distanceResults = new float[1];
            Location.distanceBetween(latitude, longitude, targetLatitude, targetLongitude, distanceResults);
            float distanceInKm = distanceResults[0] / 1000;

            String currentLocationStr = "Current :-" + latitude + " : " + longitude;
            String targetLocationStr = "Target :-" + targetLatitude + " : " + targetLongitude;

            if (distanceInKm < 1) {
                curLocation.setText(currentLocationStr);
                tarLocation.setText(targetLocationStr);
                Toast.makeText(requireContext(), "You are under office premises ", Toast.LENGTH_LONG).show();
            } else {
                curLocation.setText(currentLocationStr);
                tarLocation.setText(targetLocationStr);
                Toast.makeText(requireContext(), "You are not under office premises ", Toast.LENGTH_LONG).show();
            }
        } else {
            Toast.makeText(getContext(), "No Data", Toast.LENGTH_SHORT).show();
        }
    }
});

private void getCurrentLocation() {
    FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext());

    if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // Request location permissions if not already granted
        ActivityCompat.requestPermissions((Activity) requireContext(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
    } else {
        // Permissions already granted, request current location
        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(location -> {
                    if (location != null) {
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();

                        // Use the obtained latitude and longitude values for further processing
                        // You can compare these values with your desired geolocation
                    }
                })
                .addOnFailureListener(e -> {
                    // Handle any errors that occurred while getting the location
                });
    }
}

原代码存在的问题

  • 异步时序错误:getCurrentLocation是异步调用,调用后立刻计算距离时,latitude和longitude可能还没被赋值(getLastLocation的回调还没执行),导致用旧值或默认值计算,结果完全不准确。
  • 距离判断逻辑错误:原代码把计算出的米数转成公里后判断是否小于1(即1公里),但需求是10米,应该直接用原始米数和10比较。
  • 权限回调缺失:请求权限后,用户授权成功时没有重新触发位置获取和校验逻辑,导致授权后功能不生效。

修正后的完整代码

punchin.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        punchout.setVisibility(View.VISIBLE);
        punchin.setVisibility(View.INVISIBLE);
        curLocation.setText("");
        tarLocation.setText("");
        String androidID = getIMEINumber();

        if (androidID != null) {
            // 直接触发位置获取+校验逻辑
            getCurrentLocationAndCheck();
        } else {
            Toast.makeText(getContext(), "No Data", Toast.LENGTH_SHORT).show();
        }
    }
});

// 合并位置获取与校验逻辑,避免异步时序问题
private void getCurrentLocationAndCheck() {
    FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext());

    if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions((Activity) requireContext(), 
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
        return;
    }

    fusedLocationClient.getLastLocation()
            .addOnSuccessListener(location -> {
                if (location != null) {
                    double currentLat = location.getLatitude();
                    double currentLng = location.getLongitude();
                    double targetLatitude = 19.2185561;
                    double targetLongitude = 72.86228096;

                    // 计算距离,结果单位为米
                    float[] distanceResults = new float[1];
                    Location.distanceBetween(currentLat, currentLng, targetLatitude, targetLongitude, distanceResults);
                    float distanceInMeters = distanceResults[0];

                    String currentLocationStr = "Current :-" + currentLat + " : " + currentLng;
                    String targetLocationStr = "Target :-" + targetLatitude + " : " + targetLongitude;
                    curLocation.setText(currentLocationStr);
                    tarLocation.setText(targetLocationStr);

                    // 判断是否在10米范围内
                    if (distanceInMeters <= 10) {
                        Toast.makeText(requireContext(), "你在办公区域内", Toast.LENGTH_LONG).show();
                        // 此处可执行打卡API请求
                    } else {
                        Toast.makeText(requireContext(), "你不在办公区域内", Toast.LENGTH_LONG).show();
                    }
                } else {
                    Toast.makeText(requireContext(), "无法获取当前位置", Toast.LENGTH_SHORT).show();
                }
            })
            .addOnFailureListener(e -> {
                Toast.makeText(requireContext(), "获取位置失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
            });
}

// 处理权限请求结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 101) {
        boolean hasFineLocation = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
        boolean hasCoarseLocation = grantResults.length > 1 && grantResults[1] == PackageManager.PERMISSION_GRANTED;
        if (hasFineLocation || hasCoarseLocation) {
            // 授权成功后重新执行位置校验
            getCurrentLocationAndCheck();
        } else {
            Toast.makeText(requireContext(), "需要位置权限才能进行打卡", Toast.LENGTH_SHORT).show();
        }
    }
}

关键修改说明

  1. 合并异步逻辑:把位置获取和距离校验放到同一个方法中,确保只有拿到最新位置后才计算距离,彻底解决时序问题。
  2. 修正距离判断:直接使用distanceResults[0](单位为米)与10比较,完全符合10米半径的需求。
  3. 补充权限回调:实现onRequestPermissionsResult方法,用户授权后自动重新触发校验逻辑。
  4. 完善错误提示:增加位置获取失败、无法获取位置的提示,提升用户体验。

内容的提问来源于stack exchange,提问作者sagar raval

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:25:04