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

Android开发:Fused Location Provider Client的getCurrentLocation使用排查

Android定位获取失效的排查与修复建议

以下是针对你的定位代码失效问题的具体排查方向和修复建议:

  • 检查CancellationToken的有效性
    你代码中使用的cancellationToken如果未正确初始化或已被提前取消,会导致getCurrentLocation()直接终止,无法触发回调。确保通过CancellationTokenSource创建有效的token,且未提前调用cancel():

    CancellationTokenSource cts = new CancellationTokenSource();
    CancellationToken cancellationToken = cts.getToken();
    // 避免在任务执行前调用cts.cancel()
    
  • 增加getLastLocation()作为降级方案
    getCurrentLocation()依赖设备当前有活跃的定位源(如GPS信号、网络定位可用),否则会返回null。建议在getCurrentLocation()返回null时,调用getLastLocation()尝试获取缓存的位置:

    if (mLastKnownLocation == null) {
        mFusedLocationProviderClient.getLastLocation().addOnCompleteListener(task -> {
            if (task.isSuccessful() && task.getResult() != null) {
                mLastKnownLocation = task.getResult();
                Log.d(TAG, "使用缓存位置");
            } else {
                // 仍无位置时使用默认值
                mLastKnownLocation = new Location("");
                mLastKnownLocation.setLatitude(mDefaultLocation.latitude);
                mLastKnownLocation.setLongitude(mDefaultLocation.longitude);
            }
            // 后续执行逆地理编码逻辑
        });
    }
    
  • 确保Geocoder初始化正确
    未正确初始化的Geocoder会导致逆地理编码失败,需在主线程中传入上下文和本地化参数初始化:

    Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
    

    同时增加日志输出地址列表状态,方便排查:

    List<Address> address = geocoder.getFromLocation(..., 1);
    Log.d(TAG, "Geocoder返回地址数量:" + address.size());
    
  • 检查设备定位服务状态
    即使权限已授予,若设备定位服务(GPS/网络定位)未开启,getCurrentLocation()也无法获取位置。添加代码检查并引导用户开启:

    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    if (!isGpsEnabled && !isNetworkEnabled) {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivity(intent);
    }
    
  • 强制在主线程更新UI
    虽然FusedLocationProviderClient的回调默认在主线程,但如果上下文异常可能导致UI更新失效,需显式切换到主线程更新:

    runOnUiThread(() -> {
        locationTextView.setText(msg);
    });
    
  • 添加关键节点日志
    在getDeviceLocation()入口、任务完成回调、位置获取结果、逆地理编码结果处添加日志,精准定位哪一步出现问题:

    Log.d(TAG, "进入getDeviceLocation,权限状态:" + mLocationPermissionGranted);
    Log.d(TAG, "任务完成,是否成功:" + task.isSuccessful());
    Log.d(TAG, "获取到的位置:" + mLastKnownLocation);
    

修改后的示例代码片段

private void getDeviceLocation() {
    Log.d(TAG, "进入getDeviceLocation,权限状态:" + mLocationPermissionGranted);
    try {
        if (mLocationPermissionGranted) {
            CancellationTokenSource cts = new CancellationTokenSource();
            Task<Location> locationResult = mFusedLocationProviderClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, cts.getToken());

            locationResult.addOnCompleteListener(this, task -> {
                Log.d(TAG, "任务完成,是否成功:" + task.isSuccessful());
                if (task.isSuccessful()) {
                    mLastKnownLocation = task.getResult();
                    Log.d(TAG, "获取到的位置:" + mLastKnownLocation);
                    String currentOrDefault = "Current";

                    if (mLastKnownLocation == null) {
                        // 尝试获取缓存位置
                        mFusedLocationProviderClient.getLastLocation().addOnCompleteListener(lastTask -> {
                            if (lastTask.isSuccessful() && lastTask.getResult() != null) {
                                mLastKnownLocation = lastTask.getResult();
                                Log.d(TAG, "使用缓存位置");
                            } else {
                                Log.d(TAG, "无可用位置,使用默认值");
                                currentOrDefault = "Default";
                                mLastKnownLocation = new Location("");
                                mLastKnownLocation.setLatitude(mDefaultLocation.latitude);
                                mLastKnownLocation.setLongitude(mDefaultLocation.longitude);
                            }
                            updateLocationUI(currentOrDefault);
                        });
                    } else {
                        updateLocationUI(currentOrDefault);
                    }

                } else {
                    Log.e(TAG, "任务失败,异常:" + task.getException());
                    mLastKnownLocation = new Location("");
                    mLastKnownLocation.setLatitude(mDefaultLocation.latitude);
                    mLastKnownLocation.setLongitude(mDefaultLocation.longitude);
                    runOnUiThread(() -> {
                        locationTextView.setText("Default Location: " +
                                mLastKnownLocation.getLatitude() + ", " +
                                mLastKnownLocation.getLongitude() + "  DefaultCity");
                    });
                }
            });
        } else {
            Log.d(TAG, "权限未授予,无法获取位置");
        }
    } catch (SecurityException e) {
        Log.e(TAG, "权限异常:" + e.getMessage());
        runOnUiThread(() -> locationTextView.setText("权限异常,无法获取位置"));
    }
}

private void updateLocationUI(String currentOrDefault) {
    String city = "CorrectCity";
    try {
        Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
        List<Address> address = geocoder.getFromLocation(
                mLastKnownLocation.getLatitude(),
                mLastKnownLocation.getLongitude(), 1);
        Log.d(TAG, "Geocoder返回地址数:" + address.size());
        if (address.isEmpty()) {
            city = "No_city";
        } else {
            Address target = address.get(0);
            city = target.getLocality() != null ? target.getLocality() : target.getAdminArea();
        }
    } catch (IOException e) {
        Log.e(TAG, "Geocoder异常:" + e.getMessage());
        city = "ErrorCity";
    }

    cityName = city;
    String msg = currentOrDefault + " Location: " +
            mLastKnownLocation.getLatitude() + ", " +
            mLastKnownLocation.getLongitude() + "  " + cityName;
    Log.d(TAG, "要显示的位置信息:" + msg);
    runOnUiThread(() -> locationTextView.setText(msg));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 07:45:20