要录制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上进行测试时,什么也看不到。
由于getExternalStoragePublicDirectory
和getExternalStorageDirectory
已被弃用,因此我尝试使用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) {
}
});
答案 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);