Android API 21/22下定位无返回问题求助(非过时方案)
适配API 21/22的非过时Android定位方案
问题核心原因
- 权限逻辑缺失:API 21/22无需运行时权限,但必须在Manifest中声明定位权限且用户安装时授权,你的代码仅处理了API≥23的权限校验,低版本未做权限检查。
- LocationRequest兼容性问题:
LocationRequest.Builder是Google Play Services Location 18.0.0新增API,API21/22设备的Play Services版本可能低于该版本,导致无法正常创建请求。 - 回调线程未指定:
requestLocationUpdates最后一个参数传null,低版本系统中可能导致回调无法触发,需指定主线程Looper。
完整修正实现
1. 配置Manifest权限
确保AndroidManifest.xml中添加定位权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
2. 全版本权限校验逻辑
覆盖API21/22及更高版本的权限检查:
private boolean hasLocationPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return ActivityCompat.checkSelfPermission(requireActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(requireActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED; } else { // API21/22 权限在安装时授予,直接检查应用是否已获得权限 PackageManager pm = requireActivity().getPackageManager(); return pm.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, requireActivity().getPackageName()) == PackageManager.PERMISSION_GRANTED || pm.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, requireActivity().getPackageName()) == PackageManager.PERMISSION_GRANTED; } }
3. 兼容的LocationRequest创建方式
改用LocationRequest.create()替代LocationRequest.Builder,同时适配低版本不支持的API:
private static LocationRequest createLocationRequest() { LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationRequest.setInterval(5000); locationRequest.setFastestInterval(2000); locationRequest.setMaxWaitTime(100); locationRequest.setNumUpdates(1); // setWaitForAccurateLocation是API26+新增,API21/22不支持 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { locationRequest.setWaitForAccurateLocation(true); } return locationRequest; }
4. 修正后的定位请求代码
添加权限校验,指定主线程Looper确保回调触发:
if (!hasLocationPermission()) { Log.d("Location", "无法获取用户位置:权限未授权"); return; } Log.d("Location", "正在请求用户位置..."); FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(requireActivity()); // 保存callback引用用于后续注销 LocationCallback locationCallback = new LocationCallback() { @Override public void onLocationResult(@NonNull LocationResult locationResult) { super.onLocationResult(locationResult); Location location = locationResult.getLastLocation(); if (location != null) { Log.d("User location", location.toString()); // 处理获取到的位置数据 } else { Log.d("User location", "获取到的位置为空"); } } @Override public void onLocationAvailability(@NonNull LocationAvailability locationAvailability) { super.onLocationAvailability(locationAvailability); if (!locationAvailability.isLocationAvailable()) { Log.d("Location", "当前位置不可用"); } } }; client.requestLocationUpdates(createLocationRequest(), locationCallback, Looper.getMainLooper());
5. 额外注意事项
- Play Services依赖版本:使用兼容API21/22的版本,推荐添加:
implementation 'com.google.android.gms:play-services-location:21.0.1' - 模拟器测试:API21/22模拟器需开启GPS功能,手动设置位置后可尝试重启定位服务;
- 回调注销:在Fragment生命周期中及时注销请求,避免内存泄漏:
@Override public void onStop() { super.onStop(); if (locationCallback != null) { LocationServices.getFusedLocationProviderClient(requireActivity()) .removeLocationUpdates(locationCallback); } }
内容的提问来源于stack exchange,提问作者user21193451
相关产品推荐
相关产品推荐

