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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:50:13