【问题标题】:How to select specific video files to upload to gallery in Android Q?如何在 Android Q 中选择特定的视频文件上传到图库?
【发布时间】:2020-06-19 10:30:38
【问题描述】:

在使用 mediaRecorder 和 Camera API 录制了视频后,我正在尝试将视频保存到用户的画廊(通过保存到他们的外部电影、DCIM 目录或其他方式)。

不幸的是,我从文档或 StackOverflow 中找到的代码似乎创建了它们各自的 URI,而没有引用录制的视频或保存它的文件。具体来说,我尝试使用的代码是:

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 = context.getContentResolver();
    Uri collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
    Uri uriSavedVideo = resolver.insert(collection, valuesvideos);

    ParcelFileDescriptor pfd;

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

        assert pfd != null;
        FileOutputStream out = new FileOutputStream(pfd.getFileDescriptor());

// Get the already saved video as fileinputstream from here
            File storageDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "Folder");
            File imageFile = new File(storageDir, "testStorage");

            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();
        }

围绕它的代码和答案似乎暗示通过访问 MediaStore.VOLUME_EXTERNAL_PRIMARY 解析器可以访问保存的视频文件,但我没有看到对它的明确引用。在录制视频之前,我将分配给 mediaRecorder 的文件定义为:

static File getMediaFile(Context c) {

    File mediaStorageDir = c.getExternalFilesDir(null);
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

    return new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp + ".mp4");

}

停止视频后,我收到此错误(引用此行:Uri uriSavedVideo = resolver.insert(collection, valuesvideos);):

java.lang.UnsupportedOperationException: 未知 URI: content://media/external_primary/video/media at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java.167) ...

如何正确创建 URI 并参考已保存的视频?将文件 Uri.fromFile(f); 中的 URI 替换为 uriSavedVideo 也不起作用。

【问题讨论】:

  • Uri uriSavedVideo 是参考。将来访问所需的 uri。
  • 你在做和 update() 的结尾是 IS_PENDING == 0 吗?
  • 你帖子的主题很奇怪。
  • @blackapps Uri uriSavedVideo 似乎仍然没有提到保存视频的文件(来自 getMediaFile),您能详细说明一下吗?
  • 没有什么可详细说明的。如果您想读取文件,例如打开输入流而不是使用该 uri。您的 getMediaFile 函数与您复制的源文件有关。副本在获得的uri中。您现在有两个文件,它们彼此无关。您的视频现在保存在两个地方。我会删除第一个,因为存储空间会很快填满。

标签: android uri android-contentresolver mediastore scoped-storage


【解决方案1】:

为了将特定视频文件保存到图库,我将文件作为参数传递给new FileInputStream

其次,作为Android docs状态:

在您的应用将 IS_PENDING 的值改回 0 之前,只有您的应用可以查看该文件。

因此,根据用户@blackapps 的建议,我手动更改了该状态。修改后的代码如下:

private static void addToApi29Gallery(File file, Context context) {
    String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";

    ContentValues valuesvideos = new ContentValues();
    valuesvideos.put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/" + "Trickshott");
    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 = context.getContentResolver();
    
    Uri collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); //all video files on primary external storage
    Uri uriSavedVideo = resolver.insert(collection, valuesvideos);

    ParcelFileDescriptor pfd;

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

        assert pfd != null;
        FileOutputStream out = new FileOutputStream(pfd.getFileDescriptor());

        // Get the already saved video as fileinputstream from here.
        FileInputStream in = new FileInputStream(file);
        
        byte[] buf = new byte[8192];
        int len;
        
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        
        out.close();
        in.close();
        pfd.close();
        
        valuesvideos.clear(); 
        valuesvideos.put(MediaStore.Video.Media.IS_PENDING, 0); // Only your app can see the files until pending is turned into 0.

        context.getContentResolver().update(uriSavedVideo, valuesvideos, null, null);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-08-08
  • 2020-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多