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

使用FusedLocationProviderClient结合接近传感器获位置遇阻:卡在isSuccessful()判断

排查FusedLocationProviderClient获取位置卡在isSuccessful()的问题

我来帮你定位这个问题!你提到代码卡在task.isSuccessful()的判断里,说明getLastLocation()的任务要么执行失败,要么返回的结果有问题。咱们从几个常见的点入手分析:

1. 先补全日志,明确失败原因

你现在的onComplete里只有成功分支,完全不知道失败时的具体情况。先补上else分支,打印错误信息,这样能精准定位问题:

location.addOnCompleteListener(new OnCompleteListener() {
    @Override
    public void onComplete(@NonNull Task task) {
        if ( task.isSuccessful() ) {
            // 你的现有逻辑
        } else {
            // 新增:打印失败原因
            Log.e("LocationFail", "任务执行失败: " + task.getException());
        }
    }
});

这一步能帮你快速区分是权限问题、位置服务未开启,还是其他异常导致的任务失败。

2. 警惕getLastLocation()的局限性

getLastLocation()是个容易踩坑的方法——它只返回设备最近缓存的位置,如果设备很久没定位、位置服务刚开启,或者缓存的位置已经失效,这个方法会返回null,甚至直接导致任务失败。

如果你的需求是获取实时位置,建议替换成getCurrentLocation(),这个方法会主动触发定位(而非依赖缓存),可靠性高很多。示例代码如下:

// 先初始化LocationRequest,设置定位优先级和更新间隔
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);

// 检查设备位置设置是否满足定位要求
LocationSettingsRequest.Builder settingsBuilder = new LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest);
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> settingsTask = settingsClient.checkLocationSettings(settingsBuilder.build());

settingsTask.addOnSuccessListener(settingsResponse -> {
    // 位置设置符合要求,开始获取当前位置
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    mFusedLocationProviderClient.getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, null)
            .addOnCompleteListener(locationTask -> {
                if (locationTask.isSuccessful() && locationTask.getResult() != null) {
                    Location currentLocation = locationTask.getResult();
                    double lat = currentLocation.getLatitude();
                    double lon = currentLocation.getLongitude();
                    Log.d("LocationSuccess", "纬度: " + lat + ", 经度: " + lon);
                    // 执行你的添加标记、地图操作逻辑
                    addMarker(lat, lon);
                    final LatLng sydney = new LatLng(lat, lon);
                    mapFragment.mapView.getMapAsync(googleMap -> 
                        googleMap.addMarker(new MarkerOptions().position(sydney))
                    );
                } else {
                    Log.e("LocationError", "获取实时位置失败: " + locationTask.getException());
                }
            });
});

settingsTask.addOnFailureListener(e -> {
    if (e instanceof ResolvableApiException) {
        // 位置设置不满足(比如GPS没开),引导用户开启
        try {
            ResolvableApiException resolvableException = (ResolvableApiException) e;
            resolvableException.startResolutionForResult(this, 1001); // 1001是自定义请求码
        } catch (IntentSender.SendIntentException sendEx) {
            Log.e("SettingsError", "跳转位置设置失败: " + sendEx);
        }
    }
});

3. 权限检查的优化

你现在把权限检查放在try-catch里,但这个检查不会抛出异常,完全没必要。同时要确保:

  • Manifest文件里已经声明了ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION权限;
  • Android 6.0+设备上,已经通过动态申请流程拿到了对应权限(不能只靠Manifest声明)。

如果权限没拿到,所有定位相关的任务都会直接失败。

4. 初始化FusedLocationProviderClient的优化

你现在每次调用getDeviceLocation()都重新初始化mFusedLocationProviderClient,这既没必要也会增加资源消耗。建议在Activity的onCreate()里只初始化一次:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout);
    // 仅初始化一次
    mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
    // 其他初始化逻辑
}

最后,别忘了在onActivityResult里处理位置设置的返回结果,如果用户开启了位置服务,就重新调用获取位置的方法:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1001) {
        if (resultCode == RESULT_OK) {
            // 用户开启了位置服务,重新获取位置
            getDeviceLocation();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:48:05