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
相关产品推荐
相关产品推荐

