LocationSettingsRequest未弹出权限检查对话框问题求助
问题根源与解决方案
你这里踩了一个很常见的误区:LocationSettingsRequest检查的是系统级的位置服务是否开启(比如GPS有没有打开),而不是你的App是否获得了位置权限。这就是为什么哪怕你没给App权限,只要系统GPS是开着的,checkLocationSettings就会直接触发onSuccessListener——它根本不关心App的权限状态。
在Android 6.0(API 23)及以上,位置权限属于「危险权限」,光在清单文件里声明是没用的,必须动态向用户申请权限。只有当用户授予权限后,你再去检查系统位置设置才有意义。
接下来是具体的修复步骤:
1. 先处理动态权限请求
首先在onCreate里,我们需要先检查App是否已经获得了位置权限,如果没有就发起请求:
定义请求码常量
private static final int REQUEST_LOCATION_PERMISSIONS = 1001; private static final int REQUEST_CHECK_LOCATION_SETTINGS = 1002;
检查并请求权限的方法
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 优先处理权限请求,再检查位置设置 checkAndRequestLocationPermissions(); } private void checkAndRequestLocationPermissions() { // 检查精细位置和粗略位置权限的状态 int fineLocPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION); int coarseLocPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION); if (fineLocPerm != PackageManager.PERMISSION_GRANTED || coarseLocPerm != PackageManager.PERMISSION_GRANTED) { // 权限未授予,发起请求 ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION_PERMISSIONS ); } else { // 权限已拥有,继续检查系统位置设置 setupFusedLocationProvider(); } }
处理权限申请结果
重写onRequestPermissionsResult方法,根据用户的选择决定后续操作:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_LOCATION_PERMISSIONS) { boolean allPermsGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allPermsGranted = false; break; } } if (allPermsGranted) { // 用户同意权限,继续检查位置设置 setupFusedLocationProvider(); } else { // 权限被拒绝,提示用户权限的必要性 Toast.makeText(this, "需要授予位置权限才能使用相关功能", Toast.LENGTH_SHORT).show(); } } }
2. 保留原有的位置设置检查逻辑
你的setupFusedLocationProvider方法可以继续使用,但注意把Activity.this改成this(如果是在Activity类中),避免不必要的上下文问题:
private void setupFusedLocationProvider() { LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); LocationRequest locationRequest = new LocationRequest(); locationRequest.setInterval(10000); locationRequest.setFastestInterval(5000); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); builder.addLocationRequest(locationRequest); builder.setAlwaysShow(true); SettingsClient client = LocationServices.getSettingsClient(this); Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build()); task.addOnSuccessListener(this, locationSettingsResponse -> locationPermissionsSatisfied()); task.addOnFailureListener(this, e -> { if (e instanceof ResolvableApiException) { try { ResolvableApiException resolvable = (ResolvableApiException) e; // 这里直接用this即可,因为当前类是Activity resolvable.startResolutionForResult(this, REQUEST_CHECK_LOCATION_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { // 忽略异常 } } }); }
额外补充(针对Android 12+)
如果你的App目标SDK是31及以上,除了ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION,如果需要后台定位功能,还需要在清单中添加:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
并且在动态申请时,需要额外请求这个权限(用户会看到单独的后台权限授权弹窗)。
这样修改后,App启动时会先弹出权限请求对话框,用户授予权限后才会检查系统位置设置,完全符合你的预期流程。
内容的提问来源于stack exchange,提问作者ntakouris
相关产品推荐
相关产品推荐

