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

Android Kotlin权限重试按钮无法唤起权限弹窗问题求助

问题分析与解决方案

你的代码中点击权限请求按钮后对话框不弹出,核心原因通常是用户已永久拒绝权限(勾选了“不再询问”),此时系统不会再弹出权限请求对话框;另外还有一处代码逻辑冗余可能引发问题。以下是具体修复步骤:

1. 先确认Manifest权限声明

确保AndroidManifest.xml中已正确添加所需权限,这是基础前提:

<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

2. 修复权限请求逻辑

当用户永久拒绝权限后,直接调用launch不会触发对话框,需要先判断权限状态,引导用户前往应用设置开启权限。同时避免重复设置点击事件:

修改后的完整代码

// 异常处理
private val errorHandler = CoroutineExceptionHandler { _, throwable ->
    Log.e("SplashActivity", "Exception Error: $throwable")
}

private lateinit var multiplePermissionsLauncher: ActivityResultLauncher<Array<String>>

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_splash)
    initPermissionLauncher()
    uiStuff()
    // 提前设置按钮点击事件,避免重复绑定
    findViewById<TextView>(R.id.btnPermCheck).setOnClickListener {
        permCheck()
    }
}

private fun initPermissionLauncher() {
    multiplePermissionsLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { results ->
        val areAllPermsGranted = results.values.all { it }
        if (areAllPermsGranted) {
            lifecycleScope.launch(Dispatchers.Default + errorHandler) {
                delay(1000)
                startActivity(Intent(this@SplashActivity, ViewDevicesActivity::class.java))
                finish()
            }
        } else {
            // 显示权限提示布局
            findViewById<LinearLayout>(R.id.llPermCheck).visibility = View.VISIBLE
            // 检查是否有权限被永久拒绝
            val shouldShowRationale = permissions.any {
                shouldShowRequestPermissionRationale(it)
            }
            if (!shouldShowRationale) {
                // 引导用户去设置页开启权限
                showPermissionSettingDialog()
            }
        }
    }
}

@SuppressLint("InlinedApi")
private fun uiStuff() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        findViewById<TextView>(R.id.tvPermMessage).justificationMode =
            LineBreaker.JUSTIFICATION_MODE_INTER_WORD
    }
    val motionLayout = findViewById<MotionLayout>(R.id.clMovingParts)
    motionLayout.addTransitionListener(object : MotionLayout.TransitionListener {
        override fun onTransitionStarted(motionLayout: MotionLayout, startId: Int, endId: Int) {}
        override fun onTransitionChange(motionLayout: MotionLayout, startId: Int, endId: Int, progress: Float) {}
        override fun onTransitionCompleted(motionLayout: MotionLayout, currentId: Int) {
            permCheck()
        }
        override fun onTransitionTrigger(motionLayout: MotionLayout, triggerId: Int, positive: Boolean, progress: Float) {}
    })
}

private val permissions = arrayOf(
    Manifest.permission.SEND_SMS,
    Manifest.permission.RECEIVE_SMS,
    Manifest.permission.READ_PHONE_STATE
)

private fun permCheck() {
    // 先检查是否有未授予的权限
    val hasDeniedPerm = permissions.any {
        ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
    }
    if (hasDeniedPerm) {
        multiplePermissionsLauncher.launch(permissions)
    } else {
        // 所有权限已授予,直接跳转
        lifecycleScope.launch(Dispatchers.Default + errorHandler) {
            delay(1000)
            startActivity(Intent(this@SplashActivity, ViewDevicesActivity::class.java))
            finish()
        }
    }
}

private fun showPermissionSettingDialog() {
    AlertDialog.Builder(this)
        .setTitle("权限需求")
        .setMessage("需要开启相关权限才能正常使用应用,请前往设置页面开启权限")
        .setPositiveButton("去设置") { _, _ ->
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                data = Uri.fromParts("package", packageName, null)
            }
            startActivity(intent)
        }
        .setNegativeButton("取消", null)
        .show()
}

关键修复点说明

  • 避免重复绑定点击事件:将按钮点击事件移到onCreate中初始化,不要在权限回调里重复设置,防止多次绑定导致逻辑混乱。
  • 判断权限永久拒绝状态:通过shouldShowRequestPermissionRationale判断用户是否勾选了“不再询问”,如果返回false,则引导用户前往应用设置页开启权限。
  • 优化权限授予判断:用results.values.all { it }替代循环判断,代码更简洁。
  • 提前检查权限状态:在permCheck中先判断是否有未授予的权限,避免不必要的请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:25:33