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
相关产品推荐
相关产品推荐

