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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:25:57