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

Kotlin中Android存储权限请求逻辑异常:二次拒绝未弹设置对话框

存储权限请求逻辑修复方案

你的代码核心问题是权限拒绝后的判断逻辑搞反了,导致首次拒绝就直接弹出设置引导,不符合你要的"首次拒绝可再次请求,第二次拒绝才弹设置"的需求。以下是修复后的完整代码及关键改动说明:

修复后的代码

package com.`fun`.rapidplayer

import android.app.Dialog
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.Window
import android.widget.Button
import android.widget.LinearLayout
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat

class PermissionActivity : AppCompatActivity() {

    private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
    private val STORAGE_PERMISSION = android.Manifest.permission.WRITE_EXTERNAL_STORAGE

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_permission)

        requestPermissionLauncher =
            registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
                if (granted) {
                    navigateToMainActivity()
                } else {
                    // 权限被拒绝时,判断是否勾选了"不再询问"
                    if (!shouldShowRequestPermissionRationale(STORAGE_PERMISSION)) {
                        // 用户勾选了不再询问,弹出设置引导对话框
                        showSettingGuideDialog()
                    }
                    // 未勾选不再询问时,不做操作,让用户可以再次点击按钮发起请求
                }
            }

        val allowBtn = findViewById<Button>(R.id.Allow_Btn)
        allowBtn.setOnClickListener {
            requestStoragePermission()
        }
    }

    private fun requestStoragePermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            when {
                ContextCompat.checkSelfPermission(this, STORAGE_PERMISSION) == PackageManager.PERMISSION_GRANTED -> {
                    navigateToMainActivity()
                }
                shouldShowRequestPermissionRationale(STORAGE_PERMISSION) -> {
                    // 用户之前拒绝过权限但未勾选不再询问,再次发起请求
                    requestPermissionLauncher.launch(STORAGE_PERMISSION)
                }
                else -> {
                    // 首次请求权限,直接发起请求
                    requestPermissionLauncher.launch(STORAGE_PERMISSION)
                }
            }
        } else {
            // Android 6以下默认拥有权限,直接跳转
            navigateToMainActivity()
        }
    }

    override fun onResume() {
        super.onResume()
        if (ContextCompat.checkSelfPermission(this, STORAGE_PERMISSION) == PackageManager.PERMISSION_GRANTED) {
            navigateToMainActivity()
        }
    }

    private fun navigateToMainActivity() {
        startActivity(Intent(this, MainActivity::class.java))
        finish()
    }

    private fun showSettingGuideDialog() {
        val dialog = Dialog(this)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setCancelable(true) // 允许用户取消对话框,提升体验
        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog.setContentView(R.layout.permission_denied)
        
        val openSettingsBtn = dialog.findViewById<Button>(R.id.open_settings)
        openSettingsBtn.setOnClickListener {
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                data = Uri.fromParts("package", packageName, null)
            }
            startActivity(intent)
        }
        dialog.show()
    }
}

关键改动说明

  1. 修正权限请求逻辑判断

    • 原代码中shouldShowRequestPermissionRationale返回true时直接弹设置对话框,现在改为再次发起权限请求。这个方法返回true的场景是:用户之前拒绝过权限,但没有勾选"不再询问",此时我们应该允许用户再次尝试请求权限。
    • 只有当shouldShowRequestPermissionRationale返回false时,才说明用户勾选了"不再询问",此时弹出引导至设置的对话框。
  2. 优化权限回调逻辑

    • 在requestPermissionLauncher的回调中,权限被拒绝后不再直接弹对话框,而是先判断用户是否勾选了"不再询问",只有满足条件才弹出设置引导。
  3. 代码结构优化

    • 提取navigateToMainActivity方法,避免重复代码;
    • 定义常量STORAGE_PERMISSION,提升代码可读性;
    • 给对话框设置setCancelable(true),允许用户关闭对话框,避免强制阻塞界面;
    • 补充Android 6.0以下版本的处理逻辑,直接跳转主页面。
  4. 变量命名规范

    • 将opensettigs改为openSettingsBtn,allow改为allowBtn,符合Kotlin命名规范,提升代码可读性。

内容的提问来源于stack exchange,提问作者Ayan Mishra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:25:21