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

Android点击按钮单次获取经纬度:mFusedLocationClient调用无响应求助

解决FusedLocationClient.getLastLocation()无响应的问题

嘿,我碰到过不少开发者踩过getLastLocation()的坑——这个方法看起来简单,但经常因为各种原因哑火,尤其是你遇到的这种连回调都不触发的情况。其实核心问题在于:

getLastLocation()仅返回设备最近缓存的位置数据,如果设备从未获取过位置、缓存已过期,或者位置服务未开启,它会直接返回null,甚至不会触发任何回调。

所以更可靠的方案是使用getCurrentLocation()主动请求实时位置,下面是完整的实现步骤:

1. 配置权限与依赖

首先确保你的项目满足基础条件:

  • 在AndroidManifest.xml中添加位置权限:
    <!-- 前台获取高精度位置需要的权限 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!-- Android 12+ 需添加此权限才能申请精确位置 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    
  • 在app/build.gradle中添加Google Play Services位置依赖(可替换为最新版本):
    implementation 'com.google.android.gms:play-services-location:21.0.1'
    

2. 完整代码实现

以下是Activity中的完整逻辑,包含权限申请、位置服务检查、实时位置获取与保存:

public class MainActivity extends AppCompatActivity {
    private FusedLocationProviderClient mFusedLocationClient;
    private static final int REQUEST_LOC_PERMISSION = 100;
    private static final int REQUEST_LOC_SETTINGS = 101;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化FusedLocationClient
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        // 绑定按钮点击事件
        Button getLocBtn = findViewById(R.id.btn_get_location);
        getLocBtn.setOnClickListener(v -> fetchAndSaveLocation());
    }

    private void fetchAndSaveLocation() {
        // 第一步:检查位置权限是否已授予
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            // 未授权,发起权限申请
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_LOC_PERMISSION
            );
            return;
        }

        // 第二步:检查位置服务是否开启
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setNumUpdates(1); // 仅获取一次位置

        LocationSettingsRequest settingsRequest = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest)
                .build();

        SettingsClient settingsClient = LocationServices.getSettingsClient(this);
        settingsClient.checkLocationSettings(settingsRequest)
                .addOnSuccessListener(settingsResponse -> {
                    // 位置服务已开启,开始获取实时位置
                    mFusedLocationClient.getCurrentLocation(locationRequest, null)
                            .addOnSuccessListener(location -> {
                                if (location != null) {
                                    // 获取成功,保存经纬度
                                    double lat = location.getLatitude();
                                    double lon = location.getLongitude();
                                    // 这里替换成你的保存逻辑:比如存SharedPreferences、数据库等
                                    Log.d("LocationSuccess", "纬度: " + lat + ", 经度: " + lon);
                                    Toast.makeText(this, "位置已保存", Toast.LENGTH_SHORT).show();
                                } else {
                                    Toast.makeText(this, "未获取到位置数据", Toast.LENGTH_SHORT).show();
                                }
                            })
                            .addOnFailureListener(e -> {
                                // 获取位置失败
                                Toast.makeText(this, "获取位置失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                                Log.e("LocationError", e.getMessage());
                            });
                })
                .addOnFailureListener(e -> {
                    // 位置服务未开启,引导用户开启
                    if (e instanceof ResolvableApiException) {
                        try {
                            ResolvableApiException resolvableEx = (ResolvableApiException) e;
                            resolvableEx.startResolutionForResult(this, REQUEST_LOC_SETTINGS);
                        } catch (IntentSender.SendIntentException sendEx) {
                            Log.e("LocSettingsError", sendEx.getMessage());
                        }
                    } else {
                        Toast.makeText(this, "请开启位置服务", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    // 处理权限申请结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_LOC_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限授予,重新尝试获取位置
                fetchAndSaveLocation();
            } else {
                Toast.makeText(this, "需要位置权限才能获取经纬度", Toast.LENGTH_SHORT).show();
            }
        }
    }

    // 处理位置服务开启结果
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_LOC_SETTINGS) {
            if (resultCode == RESULT_OK) {
                // 用户开启了位置服务,重新尝试获取位置
                fetchAndSaveLocation();
            } else {
                Toast.makeText(this, "未开启位置服务,无法获取位置", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

3. 关键注意事项

  • 优先用真机测试:模拟器的位置模拟可能存在延迟或失效,真实设备测试更可靠;
  • Android 13+权限适配:申请ACCESS_FINE_LOCATION时,系统会弹出“精确位置”授权选项,需引导用户选择允许;
  • 平衡精度与功耗:如果不需要高精度位置,可以把LocationRequest.PRIORITY_HIGH_ACCURACY换成PRIORITY_BALANCED_POWER_ACCURACY;
  • 异常反馈要明确:代码中覆盖了权限、位置服务、获取失败等场景,确保用户能得到清晰的操作指引。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:00:58