Android权限弹窗不显示且onRequestPermissionResult无限循环问题
问题分析与解决方案
问题原因
当用户第二次拒绝权限并勾选「不再询问」后,Android系统会直接回调onRequestPermissionsResult而不弹出权限请求弹窗。你的原代码只要检测到权限被拒绝就无条件调用requestAllPermission,导致方法被无限循环调用。物理设备的权限机制严格遵循系统规则,而模拟器可能未完全触发该逻辑,因此只有物理设备出现异常。
修复方案
1. 添加权限请求合理性判断方法
用于检测用户是否还有机会看到权限请求弹窗(即未勾选「不再询问」):
private fun shouldShowPermissionRationale(permission: String): Boolean { return ActivityCompat.shouldShowRequestPermissionRationale(this, permission) }
2. 修改权限回调逻辑
不再无条件重复请求,而是判断用户是否永久拒绝权限,若永久拒绝则引导至应用设置页:
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == PERMISSION_REQUEST_ALL) { // 检查位置权限和短信权限是否被拒绝 val locationDenied = grantResults[0] == PackageManager.PERMISSION_DENIED || grantResults[1] == PackageManager.PERMISSION_DENIED val smsDenied = grantResults[2] == PackageManager.PERMISSION_DENIED if (locationDenied || smsDenied) { // 判断是否还能继续请求权限(用户未勾选不再询问) val canRequestLocation = shouldShowPermissionRationale(Manifest.permission.ACCESS_COARSE_LOCATION) || shouldShowPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) val canRequestSms = shouldShowPermissionRationale(Manifest.permission.SEND_SMS) if (canRequestLocation || canRequestSms) { // 仍可请求,再次弹出权限对话框 requestAllPermission("after") } else { // 用户永久拒绝,引导至设置页开启权限 Toast.makeText(applicationContext, "请在应用设置中开启必要权限以正常使用", Toast.LENGTH_SHORT).show() val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data = Uri.fromParts("package", packageName, null) } startActivity(intent) } } } }
3. 优化权限请求方法
只收集未授权的权限进行请求,避免重复请求已授权的权限:
private fun requestAllPermission(tag: String) { Log.d("permissions", tag) val neededPermissions = mutableListOf<String>() // 添加未授权的位置权限 if (!checkLocationPermission(this)) { neededPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION) neededPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION) } // 添加未授权的短信权限 if (!checkSMSPermission(this)) { neededPermissions.add(Manifest.permission.SEND_SMS) } // 仅当有需要授权的权限时才发起请求 if (neededPermissions.isNotEmpty()) { ActivityCompat.requestPermissions(this, neededPermissions.toTypedArray(), PERMISSION_REQUEST_ALL) } }
关键说明
- 当用户勾选「不再询问」后,
shouldShowRequestPermissionRationale会返回false,此时不能再重复调用权限请求,否则会触发无限循环。 - 引导用户至设置页是处理永久拒绝权限的标准做法,能提升用户体验并明确告知权限必要性。
内容的提问来源于stack exchange,提问作者Chrizlove
相关产品推荐
相关产品推荐

