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

使用FileProvider在onActivityResult中遇EACCES权限拒绝问题求助

问题解决:将录制视频从Content Uri复制到应用本地文件夹

核心错误分析

  • 查询字段错误:getRealPathFromURI中误用MediaStore.Images.Media.DATA查询视频文件,应替换为MediaStore.Video.Media.DATA,否则部分系统无法正确获取路径。
  • 冗余的FileProvider操作:onActivityResult返回的selectedMediaUri本身带有临时访问权限,无需通过自己的FileProvider生成Uri再读取,直接用ContentResolver即可访问。
  • Scoped Storage限制:Android 10+禁止直接访问外部存储的真实路径,直接操作文件会触发权限拒绝。

修正后的代码实现

简化复制逻辑(无需获取真实路径)

直接通过ContentResolver读取视频流,写入应用私有目录(无需额外权限):

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    ....
    } else if (requestCode == CAMERA_REQUEST_VIDEO) {
        if (resultCode == Activity.RESULT_OK && data != null) {
            ....
            Uri selectedMediaUri = data.getData();
            if (selectedMediaUri == null) {
                Log.e("App", "Media Uri is null");
                return;
            }
            Log.d("App", "got link:" + selectedMediaUri);
            
            // 目标文件:应用私有目录,这里用内部存储的files目录
            File fileCameraTemp = new File(getFilesDir(), "camera_result_temp.mp4");
            // 也可以用外部私有目录:getExternalFilesDir(Environment.DIRECTORY_MOVIES)
            
            try (InputStream is = getContentResolver().openInputStream(selectedMediaUri);
                 FileOutputStream fos = new FileOutputStream(fileCameraTemp)) {
                 
                byte[] buf = new byte[4096]; // 增大缓冲区提升复制效率
                int len;
                while ((len = is.read(buf)) > 0) {
                    fos.write(buf, 0, len);
                }
                Log.d("App", "视频复制成功,路径:" + fileCameraTemp.getAbsolutePath());
            } catch (IOException e) {
                Log.e("App", "复制视频失败", e);
            }
            ....
        }
    }
}

(可选)修正FileProvider配置(仅当需要分享文件时)

如果后续需要将应用内的视频分享给其他应用,需保证配置一致:

  1. 统一Manifest和代码中的authorities,比如都改为de.x.y.app.fileprovider:
<provider android:name="androidx.core.content.FileProvider" 
          android:authorities="de.x.y.app.fileprovider" 
          android:exported="false" 
          android:grantUriPermissions="true">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS" 
               android:resource="@xml/file_paths"/>
</provider>
  1. 精简file_paths.xml,只保留需要的应用内路径:
<?xml version="1.0" encoding="utf-8"?>
<paths>
     <files-path name="files" path="."/>
     <external-files-path name="external_files" path="."/>
</paths>

关键注意事项

  • 应用私有目录(getFilesDir()、getCacheDir()、getExternalFilesDir()等)无需额外存储权限,系统默认允许访问。
  • 使用try-with-resources语法自动关闭流,避免资源泄漏。
  • 该方案适配Android 7.0+全版本,包括Android 10+的Scoped Storage限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:44:52