Android视频路径转URI后VideoView播放失败问题求助
解决VideoView无法播放拍摄视频的问题
嘿,我来帮你排查下问题所在!你的代码里有两个关键问题导致VideoView播放失败,咱们一步步拆解:
1. 错误的路径获取方式
当你调用videoUri.getPath()时,拿到的并不是真实的本地文件路径——因为相机返回的intent.getData()是一个content://类型的内容Uri,它的getPath()只是Uri内部的路径段,不是文件系统里的绝对路径。你用这个无效的路径创建File对象,再转成file:// Uri,自然找不到对应的视频文件。
2. Android 7.0+的Uri安全限制
就算你拿到了正确的路径,从Android 7.0(API 24)开始,直接使用Uri.fromFile()生成的file:// Uri会触发FileUriExposedException,系统不允许这种跨应用的文件暴露方式,这也是播放失败的潜在原因。
修正方案
方案一:直接使用相机返回的Content Uri播放(最简单)
相机返回的content:// Uri本身就可以被VideoView直接识别,不需要转成file:// Uri,直接用它就行:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); // 别忘了调用super! if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) { Uri videoUri = intent.getData(); if (videoUri != null) { v.setVideoURI(videoUri); v.start(); } } }
方案二:获取真实文件路径并保存到数据库(如果需要)
如果你确实需要把视频的真实路径存到数据库,可以通过ContentResolver查询获取:
// 工具方法:从Content Uri获取真实文件路径 private String getRealPathFromContentUri(Uri contentUri) { String[] projection = {MediaStore.Video.Media.DATA}; Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null); if (cursor == null) return null; int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA); cursor.moveToFirst(); String realPath = cursor.getString(columnIndex); cursor.close(); return realPath; }
然后在onActivityResult里调用这个方法保存路径:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) { Uri videoUri = intent.getData(); if (videoUri != null) { // 获取真实路径并保存到数据库 String realVideoPath = getRealPathFromContentUri(videoUri); if (realVideoPath != null) { // 这里执行保存路径到数据库的逻辑 savePathToDatabase(realVideoPath); } // 直接用Content Uri播放 v.setVideoURI(videoUri); v.start(); } } }
方案三:从数据库读取路径后播放(Android 10+兼容)
如果后续从数据库取出路径要播放,在Android 10及以上因为Scoped Storage限制,直接用路径创建file:// Uri会报错,建议通过MediaStore重新获取Content Uri:
// 从路径获取Content Uri(适用于Android 10+) private Uri getContentUriFromPath(String filePath) { String selection = MediaStore.Video.Media.DATA + "=?"; String[] selectionArgs = {filePath}; Cursor cursor = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)); cursor.close(); return ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id); } return null; }
额外注意事项
- 确保你已经申请了
READ_EXTERNAL_STORAGE权限(Android 6.0+需要动态申请) - Android 10及以上建议优先使用Content Uri而非真实文件路径,避免Scoped Storage的限制
- 检查VideoView的布局是否正确,有没有设置足够的宽高
内容的提问来源于stack exchange,提问作者zuest
相关产品推荐
相关产品推荐

