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() } }
关键改动说明
修正权限请求逻辑判断
- 原代码中
shouldShowRequestPermissionRationale返回true时直接弹设置对话框,现在改为再次发起权限请求。这个方法返回true的场景是:用户之前拒绝过权限,但没有勾选"不再询问",此时我们应该允许用户再次尝试请求权限。 - 只有当
shouldShowRequestPermissionRationale返回false时,才说明用户勾选了"不再询问",此时弹出引导至设置的对话框。
- 原代码中
优化权限回调逻辑
- 在
requestPermissionLauncher的回调中,权限被拒绝后不再直接弹对话框,而是先判断用户是否勾选了"不再询问",只有满足条件才弹出设置引导。
- 在
代码结构优化
- 提取
navigateToMainActivity方法,避免重复代码; - 定义常量
STORAGE_PERMISSION,提升代码可读性; - 给对话框设置
setCancelable(true),允许用户关闭对话框,避免强制阻塞界面; - 补充Android 6.0以下版本的处理逻辑,直接跳转主页面。
- 提取
变量命名规范
- 将
opensettigs改为openSettingsBtn,allow改为allowBtn,符合Kotlin命名规范,提升代码可读性。
- 将
内容的提问来源于stack exchange,提问作者Ayan Mishra
相关产品推荐
相关产品推荐

