Android读取外部存储权限请求失效问题求助
Android 外部存储权限请求不弹出授权框问题排查与解决
问题场景
要实现应用内选图并在PhotoView显示、重启后保留图片的功能,需读取外部存储,但权限请求始终不弹出——代码能检测到未授权状态,却无法触发用户授权提示。每次启动应用直接显示“Permission NOT granted”,访问外部存储时报错。
现有代码
权限请求逻辑:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 未授权,请求权限 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_EXTERNAL_STORAGE) Toast.makeText(this, "Permission NOT granted", Toast.LENGTH_SHORT).show() } else { // 已授权,可访问外部存储 // 此处编写读取外部存储的代码 Toast.makeText(this, "Permission granted", Toast.LENGTH_SHORT).show() }
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" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 其他内容........ </manifest>
权限回调方法:
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == PERMISSION_REQUEST_EXTERNAL_STORAGE) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限已授予,可访问外部存储 // 此处编写读取外部存储的代码 } else { // 权限被拒绝 // 处理用户拒绝权限的情况 } } }
请求码声明:
private val PERMISSION_REQUEST_EXTERNAL_STORAGE = 1
解决方法
1. 适配Android 13+的媒体权限
从Android 13(API 33)开始,READ_EXTERNAL_STORAGE权限被废弃,系统不再处理该权限的授权请求,需改用READ_MEDIA_IMAGES权限(针对图片):
- 更新Manifest权限声明:
<!-- 适配Android 13+的图片读取权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- 兼容Android 12及以下版本 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> - 修改权限请求代码,根据系统版本选择对应权限:
val targetPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { Manifest.permission.READ_MEDIA_IMAGES } else { Manifest.permission.READ_EXTERNAL_STORAGE } if (ContextCompat.checkSelfPermission(this, targetPermission) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(targetPermission), PERMISSION_REQUEST_EXTERNAL_STORAGE) }
2. 处理权限被永久拒绝的情况
如果用户之前拒绝权限时勾选了“不再询问”,requestPermissions不会再弹出授权框,需引导用户前往应用设置手动开启:
val targetPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { Manifest.permission.READ_MEDIA_IMAGES } else { Manifest.permission.READ_EXTERNAL_STORAGE } if (ContextCompat.checkSelfPermission(this, targetPermission) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, targetPermission)) { // 向用户说明权限用途后再次请求 Toast.makeText(this, "需要读取图片权限来展示您选择的图片", Toast.LENGTH_SHORT).show() ActivityCompat.requestPermissions(this, arrayOf(targetPermission), PERMISSION_REQUEST_EXTERNAL_STORAGE) } else { // 权限被永久拒绝,跳转到应用设置页 val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data = Uri.fromParts("package", packageName, null) } startActivity(intent) } }
3. 关于请求码的说明
PERMISSION_REQUEST_EXTERNAL_STORAGE = 1是自定义的唯一标识,用来在onRequestPermissionsResult回调中区分不同的权限请求(如果应用同时请求多个权限)。这个值可以是任意非负整数,只要回调中判断的请求码和请求时的一致即可。
4. 检查Manifest权限声明位置
确保权限声明在<application>标签外部,不要嵌套在<application>内部,否则权限声明无效。
内容的提问来源于stack exchange,提问作者Deimos
相关产品推荐
相关产品推荐

