You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:32:49