将视频文件存储在 SD 卡中 Android 5
Store video files on SD card in Android 5
我正在借助 android.media.MediaRecorder
class 录制视频,它接受输出文件的路径字符串 (MediaRecorder.setOutputFile(String)
),尽管有一个版本的方法可以接受FileDescriptor
.
我需要存储巨大的视频文件,所以我想使用SD卡。为了获得相关目录的路径,我使用 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
。事实证明,生成的路径是针对“模拟”存储(/sdcard/…
)而不是真正的 SD 卡(在我的 Xperia Z3 Compact 上是 /sdcard1/
,Android 5.1.1)。
我尝试对 /sdcard1/
(以及 /storage/sdcard1
)进行硬编码,但得到一个 IOException
谈论权限拒绝。当然,我有
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我听说 4.4(又名存储访问框架)后对 SD 卡的访问发生了巨大变化,但找不到足够简单明了的解释来说明在这种情况下如何完成工作。对此的简短解决方案有帮助吗?
PS 具有硬编码路径的解决方案对我来说是可以的,因为我打算仅将此应用程序与我的 phone.
一起使用
所以我不得不按照上面提到的 Storage Access Framework.
进行“完整的循环”
第 1 步:请求创建文件
注意:下面的 fileName
是文件本身的字面名称,没有完整的(所需的)路径。例如。 myvideo.mp4
.
private void createFile(String fileName) {
String mimeType = "video/mp4";
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(intent, WRITE_REQUEST_CODE /* is some random int constant*/);
}
第 2 步:处理目录选择的回调
调用 createFile
后(参见第 1 步),将向用户提供一个系统对话框,用于选择存储文件的目录。在他们做出选择后,将使用新文件所需的 URI 触发处理程序。我们可以把它变成 FileDescriptor
并使用相应版本的 MediaRecorder.setOutputFile
.
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
if (resultData != null) {
URI outputFileUri = resultData.getData();
FileDesriptor outputFileDescriptor = getContentResolver().openFileDescriptor(outputFileUri, "w").getFileDescriptor()
mMediaRecorder.setOutputFile(outputFileDescriptor);
mMediaRecorder.start();
}
}
}
这个方法应该在someActivity
-class.
里面实现
改进空间
因此用户每次开始新视频时都必须在系统菜单中单击 Save
。当我的应用程序可以自行决定目录时,恢复 KitKat 之前的状态会很好。考虑到我的经验,如果使用“专业”应用程序,这确实是可能的。例如。 “ES Explorer”仅要求用户明确授予对SD卡的操作权限一次(使用类似的系统对话框)。
此代码应该可以解决您的问题:
public String createVideoFilePath() {
String time = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File[] pathsArray = getExternalFilesDirs(Environment.DIRECTORY_DCIM);
/通常,pathArray[1] 包含路径到
可移动 SD 上的必要文件夹
卡片。所以我们通常可以只使用 pathArray[1] 而不是使用 for statement/
在 pathArray 中搜索必要的文件
for (File f : pathsArray) {
if ((f != null) && (Environment.isExternalStorageRemovable(f))) {
return f.getPath() + File.separator +"video_"+ time + ".mp4";
}
}
return pathsArray[0].getPath() + File.separator +"video_"+ time + ".mp4";
}
此方法 returns 文件在可移动 SD 卡或模拟存储中的位置(如果可移动 SD 不存在)
只需将此方法用作 MediaRecorder.setOutputFile(String)
的参数即可
更新:
非常重要的一点是,所有位于文件夹中的文件,通过 Context. getExternalFilesDirs(String typr)
获取的文件都将在卸载您的应用程序后被删除。
我正在借助 android.media.MediaRecorder
class 录制视频,它接受输出文件的路径字符串 (MediaRecorder.setOutputFile(String)
),尽管有一个版本的方法可以接受FileDescriptor
.
我需要存储巨大的视频文件,所以我想使用SD卡。为了获得相关目录的路径,我使用 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
。事实证明,生成的路径是针对“模拟”存储(/sdcard/…
)而不是真正的 SD 卡(在我的 Xperia Z3 Compact 上是 /sdcard1/
,Android 5.1.1)。
我尝试对 /sdcard1/
(以及 /storage/sdcard1
)进行硬编码,但得到一个 IOException
谈论权限拒绝。当然,我有
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我听说 4.4(又名存储访问框架)后对 SD 卡的访问发生了巨大变化,但找不到足够简单明了的解释来说明在这种情况下如何完成工作。对此的简短解决方案有帮助吗?
PS 具有硬编码路径的解决方案对我来说是可以的,因为我打算仅将此应用程序与我的 phone.
一起使用所以我不得不按照上面提到的 Storage Access Framework.
进行“完整的循环”第 1 步:请求创建文件
注意:下面的 fileName
是文件本身的字面名称,没有完整的(所需的)路径。例如。 myvideo.mp4
.
private void createFile(String fileName) {
String mimeType = "video/mp4";
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(intent, WRITE_REQUEST_CODE /* is some random int constant*/);
}
第 2 步:处理目录选择的回调
调用 createFile
后(参见第 1 步),将向用户提供一个系统对话框,用于选择存储文件的目录。在他们做出选择后,将使用新文件所需的 URI 触发处理程序。我们可以把它变成 FileDescriptor
并使用相应版本的 MediaRecorder.setOutputFile
.
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
if (resultData != null) {
URI outputFileUri = resultData.getData();
FileDesriptor outputFileDescriptor = getContentResolver().openFileDescriptor(outputFileUri, "w").getFileDescriptor()
mMediaRecorder.setOutputFile(outputFileDescriptor);
mMediaRecorder.start();
}
}
}
这个方法应该在someActivity
-class.
改进空间
因此用户每次开始新视频时都必须在系统菜单中单击 Save
。当我的应用程序可以自行决定目录时,恢复 KitKat 之前的状态会很好。考虑到我的经验,如果使用“专业”应用程序,这确实是可能的。例如。 “ES Explorer”仅要求用户明确授予对SD卡的操作权限一次(使用类似的系统对话框)。
此代码应该可以解决您的问题:
public String createVideoFilePath() {
String time = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File[] pathsArray = getExternalFilesDirs(Environment.DIRECTORY_DCIM);
/通常,pathArray[1] 包含路径到 可移动 SD 上的必要文件夹 卡片。所以我们通常可以只使用 pathArray[1] 而不是使用 for statement/
在 pathArray 中搜索必要的文件 for (File f : pathsArray) {
if ((f != null) && (Environment.isExternalStorageRemovable(f))) {
return f.getPath() + File.separator +"video_"+ time + ".mp4";
}
}
return pathsArray[0].getPath() + File.separator +"video_"+ time + ".mp4";
}
此方法 returns 文件在可移动 SD 卡或模拟存储中的位置(如果可移动 SD 不存在)
只需将此方法用作 MediaRecorder.setOutputFile(String)
的参数即可
更新:
非常重要的一点是,所有位于文件夹中的文件,通过 Context. getExternalFilesDirs(String typr)
获取的文件都将在卸载您的应用程序后被删除。