Android麦克风权限请求陷入无限循环问题求助
解决麦克风权限请求无限循环问题
问题原因
当用户两次拒绝麦克风权限并勾选「不再询问」后,shouldShowRequestPermissionRationale()会返回false,此时调用requestPermissions()不会弹出系统权限弹窗,直接触发onRequestPermissionsResult返回未授权状态。由于checkPermissions()在onResume()中被调用,权限回调后页面回到onResume,再次触发权限请求,形成无限循环。
解决方案
核心思路是:识别权限被永久拒绝的状态,避免重复发起无效的系统权限请求,转而引导用户前往应用设置手动开启权限。
1. 新增永久权限拒绝判断方法
private fun isPermissionPermanentlyDenied(permission: String): Boolean { return !ActivityCompat.shouldShowRequestPermissionRationale(this, permission) && ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED }
2. 修改权限检查逻辑
private fun checkPermissions() { val recordAudioPermission = Manifest.permission.RECORD_AUDIO if (ContextCompat.checkSelfPermission(this, recordAudioPermission) == PackageManager.PERMISSION_GRANTED) { checkSignIn() } else { if (ActivityCompat.shouldShowRequestPermissionRationale(this, recordAudioPermission)) { explainRecordingRequest() } else { // 判断是否为永久拒绝,是则引导去设置,否则发起权限请求 if (isPermissionPermanentlyDenied(recordAudioPermission)) { showGoToSettingsDialog() } else { ActivityCompat.requestPermissions(this@MainActivity, arrayOf(recordAudioPermission), 1000) } } } }
3. 添加引导至设置的对话框
private fun showGoToSettingsDialog() { val builder = AlertDialog.Builder(this) builder.setTitle("需要麦克风权限") .setMessage("您已永久拒绝麦克风权限,请前往应用设置开启,否则无法使用相关功能") .setPositiveButton("去设置") { _, _ -> // 跳转至应用详情设置页 val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri = Uri.fromParts("package", packageName, null) intent.data = uri startActivity(intent) } .setNegativeButton("取消", null) builder.create().show() }
4. 更新权限回调处理
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) Timber.d("FLOW: received req=$requestCode, len(grants)=${grantResults.size}") when (requestCode) { 1000 -> { val permission = permissions[0] if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Timber.d("FLOW: ...granted") checkSignIn() } else { Timber.d("FLOW: ...not granted") // 权限被拒绝时,检查是否为永久拒绝 if (isPermissionPermanentlyDenied(permission)) { showGoToSettingsDialog() } } } else -> { Timber.e("FLOW: unhandled permission request for $requestCode") } } }
额外优化建议
避免在onResume()中每次都触发权限检查,可改为在进入需要权限的功能页、用户主动触发相关操作时再调用checkPermissions(),减少不必要的请求触发。
内容的提问来源于stack exchange,提问作者Yanay Lehavi
相关产品推荐
相关产品推荐

