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

Room数据库存储的视频路径在编辑页上传服务器失败求助

问题解决建议

问题场景&关键信息

  • 已将视频的Content URI存储到Room数据库:
    content://com.google.android.apps.photos.contentprovider/-1/2/content%3A%2F%2Fmedia%2Fexternal%2Fvideo%2Fmedia%2F1000019304/ORIGINAL/NONE/video%2Fmp4/1784231912
    
  • 使用getVideoPath方法将其转换为绝对路径/storage/emulated/0/Download/sample-mp4-file-small.mp4,选择视频时该转换路径可正常用于上传和播放,但从数据库取出原Content URI再转换后完全失效:
    • 上传API无法正常工作
    • VideoView加载时抛出GlideException,根因是setDataSourceCallback或setDataSource失败,状态码0x80000000

核心问题分析

谷歌相册返回的嵌套Content URI依赖临时权限,重启App或进入编辑页时权限可能已失效;同时Android 10+的Scoped Storage限制下,直接转换Content URI为绝对路径的方式本身就不可靠,路径随时可能失效。


具体解决步骤

1. 存储持久化的文件引用(推荐方案)

不要存储临时Content URI,改为:

  • 选择视频后,通过ContentResolver打开输入流,将视频文件复制到App私有目录(比如getExternalFilesDir(Environment.DIRECTORY_MOVIES)),存储该私有目录的绝对路径到Room
  • 后续编辑时直接使用私有路径,无需权限处理,上传和播放都能稳定工作
  • 若必须保留原文件,可存储MediaStore的视频ID,后续通过ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id)重新构建URI,再通过ContentResolver访问

2. 修复上传逻辑,避免依赖绝对路径

如果坚持使用Content URI,上传时直接用ContentResolver获取文件流,跳过路径转换:

// 从数据库取出URI后,直接获取输入流用于Multipart上传
InputStream inputStream = getContentResolver().openInputStream(uri);
// 将inputStream传入MultipartBody.Part,无需转换为绝对路径

3. 修复VideoView播放问题

  • 直接给VideoView设置Content URI,而非转换后的绝对路径:
    VideoView videoView = findViewById(R.id.videoView);
    videoView.setVideoURI(uri);
    videoView.start();
    
  • 若用Glide播放,确保添加权限并正确加载URI:
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    
    Glide.with(this)
         .asVideo()
         .load(uri)
         .into(videoView);
    

4. 确保Content URI的权限持久化

选择视频时,调用takePersistableUriPermission获取持久权限,避免后续访问失效:

// 获取权限后调用
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

5. 修正路径转换方法(仅适配旧系统)

若需兼容Android 9及以下,使用ContentResolver查询真实路径,避免手动解析:

public String getRealPathFromURI(Context context, Uri uri) {
    String[] projection = {MediaStore.Video.Media.DATA};
    Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
    if (cursor != null) {
        int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
        cursor.moveToFirst();
        String path = cursor.getString(columnIndex);
        cursor.close();
        return path;
    }
    return null;
}

注意:Android 10+该方法无法获取真实路径,优先使用前面的方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:00:03