Android 11/Android Q系统如何保存视频文件(以保存WhatsApp状态为例)
视频保存代码问题修复方案
现有代码的核心错误如下:
- 输出流绑定对象错误:调用
openOutputStream时传入了源视频的vidUri,应该传入你新插入到MediaStore生成的目标视频Uri - 存在冗余错误代码:多写了
Uri videoFileUri = contentResolver.insert(vidUri, contentValues)这行无效逻辑,会引发异常 - 未写入实际视频数据:仅创建了空的视频文件占位,没有把源Uri的视频内容拷贝到新文件的输出流中,相当于保存了空文件,自然无法播放
修复后的完整代码
public void saveVideo(String name, Uri vidUri) { OutputStream fileOutputStream = null; InputStream inputStream = null; Uri videoUri; try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { ContentResolver contentResolver = context.getApplicationContext().getContentResolver(); ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_MOVIES + "/V Troid/WhatsApp"); // 插入获取目标视频的Uri videoUri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues); if (videoUri == null) { throw new IOException("无法创建目标视频文件"); } // 分别打开源视频输入流、目标视频输出流 inputStream = contentResolver.openInputStream(vidUri); fileOutputStream = contentResolver.openOutputStream(videoUri); if (inputStream == null || fileOutputStream == null) { throw new IOException("无法打开文件读写流"); } // 拷贝视频数据 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { inputStream.transferTo(fileOutputStream); } else { byte[] buffer = new byte[8192]; int len; while ((len = inputStream.read(buffer)) != -1) { fileOutputStream.write(buffer, 0, len); } } // 强制刷新缓冲数据写入文件 fileOutputStream.flush(); Toast.makeText(context.getApplicationContext(), "视频保存成功", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { Toast.makeText(context.getApplicationContext(), "保存失败:\n" + e.getMessage(), Toast.LENGTH_SHORT).show(); } finally { // 手动关闭流避免资源泄漏 try { if (inputStream != null) inputStream.close(); if (fileOutputStream != null) fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
适配Android11说明:当前逻辑完全符合分区存储要求,写入公共媒体目录不需要申请
MANAGE_EXTERNAL_STORAGE权限,仅需要确保你对传入的源vidUri有读取权限即可:Android13+需申请READ_MEDIA_VIDEO权限,Android12及更低版本需申请READ_EXTERNAL_STORAGE权限。
内容的提问来源于stack exchange,提问作者Garvit
相关产品推荐
相关产品推荐

