Kotlin安卓应用权限对话框不显示问题求助
问题:Android权限请求对话框不弹出,直接显示Permission Denied Toast
我正在开发基于Kotlin的Android大学作业应用,需要将图片存入SQLite数据库。请求相册权限的代码运行时,权限对话框没弹出,直接显示“Permission denied”的Toast。
源代码
package com.example.final_project import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.os.Bundle import android.provider.MediaStore import android.widget.Button import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat class ItemAdder : AppCompatActivity() { @SuppressLint("MissingInflatedId") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.add_menu) val image_button = findViewById<Button>(R.id.image_button) image_button.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ if (checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)==PackageManager.PERMISSION_DENIED){ val permissions = arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE) ActivityCompat.requestPermissions(this, permissions, PERMISSION_CODE) } else{ chooseImageGallery() } }else{ chooseImageGallery() } } companion object { private val IMAGE_CHOOSE = 1000; private val PERMISSION_CODE = 10301; private val REQUEST_CODE = 13 } private fun chooseImageGallery() { // This is irrelevant to the problem } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when(requestCode){ PERMISSION_CODE - > { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){ chooseImageGallery() }else{ Toast.makeText(this,"Permission denied", Toast.LENGTH_SHORT).show() } } } } }
Android Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.AppCompat" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.AppCompat"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ItemAdder" android:exported="false" android:theme="@style/Theme.AppCompat"/> </application> </manifest>
Gradle Build
plugins { alias(libs.plugins.android.application) alias(libs.plugins.jetbrains.kotlin.android) } android { namespace = "com.example.final_project" compileSdk = 34 defaultConfig { applicationId = "com.example.final_project" minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.5.1" } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } } dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.ui) implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) implementation(libs.androidx.appcompat) implementation(libs.androidx.constraintlayout) implementation(libs.androidx.recyclerview) implementation(libs.androidx.recyclerview.selection) implementation(libs.androidx.cardview) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) }
解决方案
1. 修复onRequestPermissionsResult中的语法错误
代码里PERMISSION_CODE后存在错误的换行和符号(- >),导致when分支无法匹配请求码,直接触发拒绝Toast。修正后代码:
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when(requestCode){ PERMISSION_CODE -> { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){ chooseImageGallery() }else{ Toast.makeText(this,"Permission denied", Toast.LENGTH_SHORT).show() } } } }
2. 适配Android 13+的媒体权限
你的targetSdk为34(Android 13+),READ_EXTERNAL_STORAGE在API 33及以上已被废弃,需使用READ_MEDIA_IMAGES权限:
- 更新Manifest:添加API33+专属权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33"/>
- 更新权限请求逻辑:根据系统版本动态选择请求的权限
image_button.setOnClickListener { val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { android.Manifest.permission.READ_MEDIA_IMAGES } else { android.Manifest.permission.READ_EXTERNAL_STORAGE } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ if (checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED){ val permissions = arrayOf(permission) ActivityCompat.requestPermissions(this, permissions, PERMISSION_CODE) } else{ chooseImageGallery() } }else{ chooseImageGallery() } }
3. 处理权限被永久拒绝的情况
若用户之前拒绝权限时勾选了“不再询问”,requestPermissions不会弹出对话框,需引导用户前往设置页开启权限:
image_button.setOnClickListener { val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { android.Manifest.permission.READ_MEDIA_IMAGES } else { android.Manifest.permission.READ_EXTERNAL_STORAGE } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ if (checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED){ // 显示权限必要性说明 if (shouldShowRequestPermissionRationale(permission)) { Toast.makeText(this, "需要访问相册来选择图片", Toast.LENGTH_SHORT).show() } val permissions = arrayOf(permission) ActivityCompat.requestPermissions(this, permissions, PERMISSION_CODE) } else{ chooseImageGallery() } }else{ chooseImageGallery() } }
在权限拒绝分支中添加跳转设置页逻辑:
// 替换原拒绝分支代码 else { if (!shouldShowRequestPermissionRationale(permission)) { // 跳转到应用设置页 val intent = android.content.Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri = android.net.Uri.fromParts("package", packageName, null) intent.data = uri startActivity(intent) Toast.makeText(this, "请在设置中开启相册权限", Toast.LENGTH_SHORT).show() } else { Toast.makeText(this,"Permission denied", Toast.LENGTH_SHORT).show() } }
内容的提问来源于stack exchange,提问作者Marcus Chan
相关产品推荐
相关产品推荐

