Android 6.0设备mFusedLocationClient.requestLocationUpdates返回重复坐标问题
你遇到的这个情况绝对不是巧合,在Android 6.0的部分设备上这种现象很常见,我给你详细分析原因和解决方案:
为什么装Google Maps后就正常了?
Android 6.0开始,多数厂商的系统定位服务依赖Google Play Services提供的核心定位组件。如果设备上的Google Play Services组件不完整、未激活或者出现异常,FusedLocationProvider会 fallback 到厂商预设的固定测试坐标(也就是你看到的重复坐标)。而Google Maps在启动时会强制触发Google Play Services定位模块的初始化与校验,自动修复组件的异常状态,所以之后你的App就能获取到真实的位置数据了。
你的代码中需要优化的点
先看你贴的代码,有几个细节可能加重了这个问题:
- 权限不匹配:你设置了
LocationRequest.PRIORITY_HIGH_ACCURACY(高精度定位),但只请求了ACCESS_COARSE_LOCATION权限,这种权限和优先级不匹配的情况,可能导致定位服务无法正常获取高精度信号,进而返回缓存的固定坐标。 - 过度依赖getLastLocation:
getLastLocation()本身是获取缓存的最后一次定位结果,很可能就是那个固定坐标,你应该把requestLocationUpdates的回调作为获取实时位置的主要来源。 - AsyncTask的不当使用:用AsyncTask来处理定位服务的异步逻辑不太合适,不仅容易引发生命周期泄漏,而且定位服务本身就是异步的,没必要再套一层AsyncTask。
具体修复方案
1. 修正权限请求
高精度定位需要ACCESS_FINE_LOCATION权限,所以权限请求要同时申请两个定位权限:
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION_PERMISSION);
并且在权限回调中,确认两个权限都被授予后再启动定位流程。
2. 优化LocationRequest配置
增加最小位移参数,避免无意义的位置更新,同时确保定位参数合理:
mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(10000); // 正常更新间隔 mLocationRequest.setFastestInterval(5000); // 最快更新间隔 mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationRequest.setSmallestDisplacement(10); // 位移超过10米才更新
3. 调整定位逻辑,以实时回调为主
把getLastLocation()作为备选方案,主要依赖LocationCallback获取实时位置:
private void startLocationUpdates() { // 先检查权限 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION_PERMISSION); return; } gPSTracker.mFusedLocationClient.requestLocationUpdates(mLocationRequest, new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) { // 回调为空时,尝试获取缓存位置 fallbackToLastLocation(); return; } // 遍历获取最新位置 for (Location location : locationResult.getLocations()) { if (location != null) { updateAppLocation(location); } } } }, Looper.getMainLooper()); // 指定主线程Looper,避免线程问题 } // 备选获取缓存位置的方法 private void fallbackToLastLocation() { gPSTracker.mFusedLocationClient.getLastLocation() .addOnSuccessListener(location -> { if (location != null) { updateAppLocation(location); } }); } // 统一处理位置更新 private void updateAppLocation(Location location) { gPSTracker.location = location; // 排除0坐标的无效数据 if (location.getLatitude() != 0 && location.getLongitude() != 0) { isLocationReady = true; runOnUiThread(this::openLocation); } }
4. 提前检查Google Play Services状态
在启动定位前,先确认Google Play Services是否可用,避免组件异常导致的定位失败:
private boolean checkGooglePlayServices() { GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); int resultCode = apiAvailability.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (apiAvailability.isUserResolvableError(resultCode)) { // 弹出修复对话框 apiAvailability.getErrorDialog(this, resultCode, 9001).show(); } else { Toast.makeText(this, "设备不支持Google Play Services,无法获取精准位置", Toast.LENGTH_LONG).show(); } return false; } return true; }
在你的ActivateLocation任务开始前,调用这个方法检查:
@Override protected Void doInBackground(Context... contexts) { if (!checkGooglePlayServices()) { return null; } // 原有的定位逻辑... }
最后总结
装Google Maps后恢复正常是因为它触发了Google Play Services定位组件的修复,而你的代码在权限、定位逻辑上的小问题放大了这个异常。按照上面的方案调整后,应该能解决固定坐标的问题,同时提升定位的稳定性。
内容的提问来源于stack exchange,提问作者Williams Abiola

