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
相关产品推荐
相关产品推荐

