Android SDK 33定位权限始终被拒问题求助
Target SDK 33下定位权限请求无弹窗且被拒的解决方案
问题描述
将应用迁移至Target SDK 33后,请求ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限时,权限始终被拒且未弹出请求对话框。已在Manifest中添加对应权限,使用官方推荐的ActivityResultContracts.RequestMultiplePermissions方式请求,迁移前(Target SDK 32)一切正常,相机、蓝牙权限请求正常,仅定位权限无效。
已配置的Manifest权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
权限请求核心代码:
private ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(new ActivityResultContracts .RequestMultiplePermissions(), result -> { Boolean fineLocationGranted = result.getOrDefault( Manifest.permission.ACCESS_FINE_LOCATION, false); Boolean coarseLocationGranted = result.getOrDefault( Manifest.permission.ACCESS_COARSE_LOCATION, false); if (fineLocationGranted != null && fineLocationGranted) { Log.d(TAG, "permissions granted"); // 执行定位相关操作 } else if (coarseLocationGranted != null && coarseLocationGranted) { Log.d(TAG, "Only approximate location access granted"); } else { Log.e(TAG, "location permission denied"); } } ); // 权限检查与请求触发逻辑 if (ActivityCompat.checkSelfPermission(DashboardActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(DashboardActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ModalDialog.Builder permissionInfoDialogBuilder = new ModalDialog.Builder(DashboardActivity.this); permissionInfoDialogBuilder.setType(ModalDialog.Type.DEFAULT_INFO) .setPositiveButton(android.R.string.ok, v -> { Log.d(TAG, "requesting location permission"); locationPermissionRequest.launch(new String[]{ Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }); }) .setTextNegative(android.R.string.cancel) .setTitle(R.string.dashboard_request_location_permission_title) .setMessage(R.string.dashboard_request_location_permission_text) .setCloseable(false); permissionInfoDialogBuilder.create().show(); return; }
核心原因及解决办法
1. 未同步升级compileSdkVersion至33
当targetSdkVersion设置为33,但compileSdkVersion仍低于33时,权限请求逻辑会出现兼容性问题,系统无法正确解析SDK33的权限规则,导致直接返回拒绝且不弹窗。
解决步骤:
修改Module级别的build.gradle文件,将compileSdkVersion升级至33:
android { compileSdkVersion 33 // 其他配置... defaultConfig { targetSdkVersion 33 // 其他配置... } }
2. 未处理权限永久拒绝的场景
如果用户之前已拒绝权限并勾选“不再询问”,此时直接发起权限请求,系统不会弹出对话框,直接返回拒绝。需要提前判断权限状态,引导用户到设置页开启权限。
优化后的权限检查逻辑:
boolean fineLocationDenied = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED; boolean coarseLocationDenied = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED; if (fineLocationDenied || coarseLocationDenied) { // 判断是否需要显示权限解释(用户未勾选"不再询问") boolean shouldShowRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION); if (shouldShowRationale) { // 显示自定义提示后发起请求 ModalDialog.Builder permissionInfoDialogBuilder = new ModalDialog.Builder(DashboardActivity.this); permissionInfoDialogBuilder.setType(ModalDialog.Type.DEFAULT_INFO) .setPositiveButton(android.R.string.ok, v -> { Log.d(TAG, "requesting location permission"); locationPermissionRequest.launch(new String[]{ Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }); }) .setTextNegative(android.R.string.cancel) .setTitle(R.string.dashboard_request_location_permission_title) .setMessage(R.string.dashboard_request_location_permission_text) .setCloseable(false); permissionInfoDialogBuilder.create().show(); } else { // 权限已被永久拒绝,引导用户到应用设置页 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } return; }
3. 后台位置权限的额外需求(若应用需要后台定位)
如果你的应用需要在后台访问位置,除了前台权限,还需在Manifest中添加ACCESS_BACKGROUND_LOCATION权限,且Android 13要求后台权限必须在获得前台权限后单独请求。
Manifest添加后台权限:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
单独请求后台权限示例:
// 确保已获得前台位置权限后再发起请求 if (fineLocationGranted != null && fineLocationGranted || coarseLocationGranted != null && coarseLocationGranted) { ActivityResultLauncher<String> backgroundLocationLauncher = registerForActivityResult( new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { Log.d(TAG, "Background location access granted"); } else { Log.e(TAG, "Background location access denied"); } } ); backgroundLocationLauncher.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION); }
内容的提问来源于stack exchange,提问作者Herrmann_wst
相关产品推荐
相关产品推荐

