将视频插入图库[Android Q]

时间:2019-09-13 19:47:10

标签: java android android-external-storage android-mediascanner android-10.0

要录制SurfeceView,我正在使用第三方library,该库需要一个路径,在该路径中,本例中保存的输出(录制的视频)为 savedVideoPath

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

停止录制后,应该使用 savedVideoPath 作为路径保存视频,当我测试代码时,也就是说,当我打开Gallery应用程序时,我会在此处看到保存的视频,但是当我在Android Q上进行测试时,什么也看不到。

由于getExternalStoragePublicDirectorygetExternalStorageDirectory已被弃用,因此我尝试使用getExternalFilesDir,如下所示:

private void getPath() {
        String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
        fileName = videoFileName;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            File imageFile = null;
            File storageDir = new File(getExternalFilesDir(Environment.DIRECTORY_MOVIES), "Folder");
            source = storageDir;
            boolean success = true;
            if (!storageDir.exists()) {
                success = storageDir.mkdirs();
            }
            if (success) {
                imageFile = new File(storageDir, videoFileName);
                savedVideoPath = imageFile.getAbsolutePath();
            }
        } 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();
            }
        }
    }

录制停止后,我进入 Files Explorer应用> Android>数据> com.packageName>文件>电影>文件夹,我可以在那里看到所有保存的视频,但是看不到他们在画廊。

我尝试使用Intent.ACTION_MEDIA_SCANNER_SCAN_FILE刷新图库,但不幸的是,它不起作用。

我也尝试过MediaScannerConnection

 MediaScannerConnection.scanFile(context, new String[]{savedVideoPath}, new String[]{"video/mp4"}, new MediaScannerConnection.MediaScannerConnectionClient() {
            public void onMediaScannerConnected() {
            }

            public void onScanCompleted(String s, Uri uri) {

            }
        });
  • 有人可以帮助我解决此问题吗?我坚持了将近2天

3 个答案:

答案 0 :(得分:5)

这是我的解决方案-将照片/视频保存到图库。

private fun saveMediaFile2(filePath: String?, isVideo: Boolean, fileName: String) {
filePath?.let {
    val context = MyApp.applicationContext
    val values = ContentValues().apply {
        val folderName = if (isVideo) {
            Environment.DIRECTORY_MOVIES
        } else {
            Environment.DIRECTORY_PICTURES
        }
        put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
        put(MediaStore.Images.Media.MIME_TYPE, MimeUtils.guessMimeTypeFromExtension(getExtension(fileName)))
        put(MediaStore.Images.Media.RELATIVE_PATH, folderName + "/${context.getString(R.string.app_name)}/")
        put(MediaStore.Images.Media.IS_PENDING, 1)
    }

    val collection = if (isVideo) {
        MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    } else {
        MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    }
    val fileUri = context.contentResolver.insert(collection, values)

    fileUri?.let {
        if (isVideo) {
            context.contentResolver.openFileDescriptor(fileUri, "w").use { descriptor ->
                descriptor?.let {
                    FileOutputStream(descriptor.fileDescriptor).use { out ->
                        val videoFile = File(filePath)
                        FileInputStream(videoFile).use { inputStream ->
                            val buf = ByteArray(8192)
                            while (true) {
                                val sz = inputStream.read(buf)
                                if (sz <= 0) break
                                out.write(buf, 0, sz)
                            }
                        }
                    }
                }
            }
        } else {
            context.contentResolver.openOutputStream(fileUri).use { out ->
                val bmOptions = BitmapFactory.Options()
                val bmp = BitmapFactory.decodeFile(filePath, bmOptions)
                bmp.compress(Bitmap.CompressFormat.JPEG, 90, out)
                bmp.recycle()
            }
        }
        values.clear()
        values.put(if (isVideo) MediaStore.Video.Media.IS_PENDING else MediaStore.Images.Media.IS_PENDING, 0)
        context.contentResolver.update(fileUri, values, null, null)
    }
}
}

答案 1 :(得分:0)

最后,我已经通过在android:requestLegacyExternalStorage="true"上添加manifest来解决问题,这是一个临时解决方案。

如果有人遇到相同的问题,请通过 CommonsWare

进行检查The Death of External Storage: The End of the Saga(?)

答案 2 :(得分:0)

您必须更改库才能使其与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
        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);