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

Android 11出现FileSystemException权限拒绝错误求助(Android 7正常)

Android 11 外部存储权限拒绝(errno=13)问题解决方案

针对你遇到的Android 11设备上无法访问指定路径文件、提示权限拒绝的问题,以下是针对性的排查和解决步骤:

1. 确认requestLegacyExternalStorage配置位置正确

该属性必须直接放在AndroidManifest.xml的<application>标签下,而非<activity>或其他标签内,否则不会生效。正确配置示例:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:requestLegacyExternalStorage="true" <!-- 必须配置在此处 -->
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.MyApp">
    <!-- 活动、服务等其他配置 -->
</application>

2. Android 11 存储权限核心限制:无法直接访问其他应用私有目录

你的目标路径/storage/emulated/0/VidMate/download/属于第三方应用(VidMate)的私有存储目录,在Android 11(API 30)及以上版本中,即使持有WRITE_EXTERNAL_STORAGE权限,系统也会禁止直接访问这类目录——这是Android 11开始强制推行的存储沙箱化限制。

对应解决方法:

  • 方案1:用系统文件选择器让用户手动选择文件
    通过ACTION_OPEN_DOCUMENT唤起系统文件选择器,让用户选择目标MP3文件,获取文件的Uri后进行操作。示例代码:

    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
        addCategory(Intent.CATEGORY_OPENABLE)
        type = "audio/mpeg"
    }
    startActivityForResult(intent, REQUEST_PICK_FILE)
    

    在onActivityResult中处理返回的Uri即可读取文件内容。

  • 方案2:修改存储路径到自身应用专属目录
    如果是你自己下载的文件,不要写入其他应用的目录,改为写入自身应用的外部存储目录,该目录无需额外权限即可访问:

    val musicDir = context.getExternalFilesDir(Environment.DIRECTORY_MUSIC)
    val targetFile = File(musicDir, "your_file_name.mp3")
    // 后续读写操作直接使用targetFile
    
  • 方案3:使用MediaStore API访问媒体文件
    若目标文件属于媒体文件(如音频),可以通过MediaStore API查询并访问,无需直接操作文件路径。示例代码(查询指定名称的音频文件):

    val projection = arrayOf(MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME)
    val selection = "${MediaStore.Audio.Media.DISPLAY_NAME} = ?"
    val selectionArgs = arrayOf("Sooraj_Dooba_Hain...(256k).mp3") // 替换为目标文件名
    val cursor = contentResolver.query(
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
        projection,
        selection,
        selectionArgs,
        null
    )
    cursor?.use {
        if (it.moveToFirst()) {
            val id = it.getLong(it.getColumnIndexOrThrow(MediaStore.Audio.Media._ID))
            val uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id)
            // 通过uri读取文件内容
            val inputStream = contentResolver.openInputStream(uri)
        }
    }
    

3. 确保完成动态权限申请

即使在Manifest中声明了权限,Android 6.0(API 23)及以上版本仍需在运行时动态申请WRITE_EXTERNAL_STORAGE权限。示例代码:

private const val REQUEST_STORAGE_PERMISSION = 1001

// 检查并申请权限
fun checkStoragePermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) 
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
            REQUEST_STORAGE_PERMISSION
        )
    }
}

// 处理权限申请结果
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == REQUEST_STORAGE_PERMISSION) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限申请成功,执行文件操作
        } else {
            // 权限被拒绝,提示用户开启权限
        }
    }
}

4. 排查文件名特殊字符问题

目标文件名包含单引号、竖线等特殊字符,虽然Android 7能兼容,但Android 11的文件系统对文件名合法性检查更严格,建议将特殊字符替换为下划线(_)或其他合法字符,避免潜在的路径解析问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:27:32