【问题标题】:Save and Insert video to gallery on Android 10在 Android 10 上保存并插入视频到图库
【发布时间】:2020-01-15 07:29:46
【问题描述】:

我正在尝试将视频保存到图库,以下代码适用于除 Android Q 之外的所有 Android 版本:

private void getPath() {
    String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    ContentResolver resolver = getContentResolver();
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, videoFileName);
    contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
    contentValues.put(
        MediaStore.MediaColumns.RELATIVE_PATH, 
        "Movies/" + "Folder");
    contentValues.put(MediaStore.Video.Media.IS_PENDING, 1);
    Uri collection = 
        MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
    Uri videoUri = resolver.insert(collection, contentValues);
    if (videoUri != null) {
        try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(videoUri, "w", null)) {
            OutputStream outputStream = null;
            if (pfd != null) {
                outputStream = resolver.openOutputStream(videoUri);
                outputStream.flush();
                outputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    contentValues.clear();
    contentValues.put(MediaStore.Video.Media.IS_PENDING, 0);
    if (videoUri != null) {
        resolver.update(videoUri, contentValues, null, null);
    }
    } else {
        File storageDir = new File(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
            + "/Folder");
        boolean success = true;
        if (!storageDir.exists()) {
            success = storageDir.mkdirs();
        }
        if (success) {
            File videoFile = new File(storageDir, videoFileName);
            savedVideoPath = videoFile.getAbsolutePath();
        }
    }
}

我也尝试使用 get getExternalFilesDir() ,但不起作用,图库中没有创建视频

String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    File imageFile = null;
    File storageDir = new File(
        getExternalFilesDir(Environment.DIRECTORY_DCIM),
        "Folder");
    boolean success = true;
    if (!storageDir.exists()) {
        success = storageDir.mkdirs();
    }
    if (success) {
        imageFile = new File(storageDir, videoFileName);
    }
    savedVideoPath = imageFile.getAbsolutePath();

我使用第三方库录制SurfaceView,这个库需要保存录制视频的路径:

 mRenderPipeline = EZFilter.input(this.effectBmp)
                    .addFilter(new GalleryEffects().getEffect(VideoMaker.this, i))
                    .enableRecord(savedVideoPath, true, false)
                    .into(mRenderView);

录制视频完成后,录制的视频以给定路径 savedVideoPath 保存,除了 Android Q

之外的所有 android 版本都可以正常工作

保存视频后,当我检查时,我在图库中得到一个空视频

【问题讨论】:

  • 您的文件输出流在哪里?在上面的代码中,你只是创建了一个目录和一个文件。
  • @MohanSaiManthri 谢谢你的评论,其实我想创建一个使用它的路径
  • @MohanSaiManthri 你能再检查一下问题吗,我已经更新了
  • @MouaadAbdelghafourAITALI 你找到解决方案了吗??
  • @ParagPawar ,只是一个临时解决方案,我通过在 Application 标签内添加 android:requestLegacyExternalStorage="true" 结束了这个

标签: java android mediastore android-mediascanner android-10.0


【解决方案1】:

我已在您的另一篇文章中回答您... 您需要一个输入流(文件、位图等)并从输入文件写入一个输出流。

您必须更改库才能使其与 Android Q 一起使用。如果您不能这样做,您可以将视频复制到媒体库,然后删除在 getExternalFilesDir() 中创建的旧视频。在此之后,您拥有视频的 uri,并且可以使用 uri 做您想做的事情

如果您使用 getExternalFilesDir() 保存了视频,则可以在此处使用我的示例:您获得的媒体 uri 是“uriSavedVideo”。这只是一个例子。还应在后台复制大视频。

String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";

ContentValues valuesvideos;
valuesvideos = new ContentValues();
valuesvideos.put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/" + "Folder");
valuesvideos.put(MediaStore.Video.Media.TITLE, videoFileName);
valuesvideos.put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName);
valuesvideos.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
valuesvideos.put(
    MediaStore.Video.Media.DATE_ADDED, 
    System.currentTimeMillis() / 1000);
valuesvideos.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());
valuesvideos.put(MediaStore.Video.Media.IS_PENDING, 1);

ContentResolver resolver = mContext.getContentResolver();
Uri collection = 
    MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri uriSavedVideo = resolver.insert(collection, valuesvideos);
ParcelFileDescriptor pfd;

try {
    pfd = mContext.getContentResolver().openFileDescriptor(uriSavedVideo, "w");

    FileOutputStream out = new FileOutputStream(pfd.getFileDescriptor());
    // Get the already saved video as fileinputstream from here
    File storageDir = new File(
        mContext.getExternalFilesDir(Environment.DIRECTORY_MOVIES), 
        "Folder");
    File imageFile = new File(storageDir, "Myvideo");
    FileInputStream in = new FileInputStream(imageFile);

    byte[] buf = new byte[8192];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }

    out.close();
    in.close();
    pfd.close();
} catch (Exception e) {
    e.printStackTrace();
}

valuesvideos.clear();
valuesvideos.put(MediaStore.Video.Media.IS_PENDING, 0);
mContext.getContentResolver().update(uriSavedVideo, valuesvideos, null, null);

【讨论】:

  • 我可以使用任何文件管理器应用访问这个保存的视频文件吗?
  • 有什么办法不复制吗?
  • 什么意思?录制视频并将其直接插入媒体存储?
  • 查看 Android 文档中的 this code example。对于 Android Q,您必须使用 VOLUME_EXTERNAL_PRIMARY 而不是 EXTERNAL_CONTENT_URI
【解决方案2】:

我想创建一个使用它的路径

您从MediaStore 获得Uri。没有“路径”。 Uri 不仅不能转换为路径,而且您在 Android 10 及更高版本上没有对该位置的文件系统访问权限。

摆脱这个:

        if (videoUri != null) {
            savedVideoPath = getRealPathFromURI(videoUri);
        }

因为它不起作用。

将其替换为您的代码,以将您的视频写入Uri 标识的位置。使用resolver.openOutputStream()OutputStream 获取到该位置。特别是,您调用resolver.update() 以获得0 中的IS_PENDING 之前执行此操作,因为它明确表示“我已完成对Uri 的写信;您现在可以使用该内容了” .

或者,使用您确实可以访问的文件系统位置之一,例如Context 上的getExternalFilesDir(),并去掉MediaStore 的东西。

【讨论】:

  • 如果马克用“使用 resolver.openOutputStream()”回答的每一个问题都能得到一分钱,他就会成为全球首富。
  • @pic: "你能告诉我如何从 OutputStream 中获取位置吗" -- 抱歉,我不知道你的意思。
  • 如何使用 MediaStore 将 getExternalFilesDir 中保存的文件移动到公共 DCIM 或电影文件夹?
猜你喜欢
  • 2016-02-25
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 2020-01-15
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
相关资源
最近更新 更多