当前位置: 首页 > 知识库问答 >
问题:

使用File对象在Android(API>24)中捕获和保存视频?

谭修竹
2023-03-14

我想录制一段视频,录制5秒后保存。我有以下在API上运行良好的代码

代码:

public void startRecording()
{
    File mediaFile = new
            File(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
            + "/myvideo.mp4");


    Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT,5);
    fileUri = Uri.fromFile(mediaFile);

    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
    startActivityForResult(intent, VIDEO_CAPTURE);
}

protected void onActivityResult(int requestCode,
                                int resultCode, Intent data) {

    if (requestCode == VIDEO_CAPTURE) {
        if (resultCode == RESULT_OK) {
            Toast.makeText(this, "Video has been saved to:\n" +
                    data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(this, "Video recording cancelled.",
                    Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "Failed to record video",
                    Toast.LENGTH_LONG).show();
        }
    }
}

错误:

2019-10-08 01:15:43.483 21573-21573/com.mobilecomputing.learn2sign E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.mobilecomputing.learn2sign, PID: 21573
    android.os.FileUriExposedException: file:///storage/emulated/0/myvideo.mp4 exposed beyond app through ClipData.Item.getUri()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:1978)
        at android.net.Uri.checkFileUriExposed(Uri.java:2371)
        at android.content.ClipData.prepareToLeaveProcess(ClipData.java:963)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10228)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10213)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1854)
        at android.app.Activity.startActivityForResult(Activity.java:4599)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:676)
        at android.app.Activity.startActivityForResult(Activity.java:4557)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:663)
        at com.mobilecomputing.learn2sign.PlayHelpVideo.startRecording(PlayHelpVideo.java:125)
        at com.mobilecomputing.learn2sign.PlayHelpVideo$1.onClick(PlayHelpVideo.java:46)
        at android.view.View.performClick(View.java:6669)
        at android.view.View.performClickInternal(View.java:6638)
        at android.view.View.access$3100(View.java:789)
        at android.view.View$PerformClick.run(View.java:26145)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6898)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

我检查了,错误是因为文件对象的语法,API不支持它

虽然我可以找到其他工作的代码,我很好奇,如果这个代码有一个小的调整,可以使它的API工作

有人能帮我吗?

编辑:

我尝试过:https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en但这样做也会导致应用程序在API 22上崩溃。

更新:

根据回复的答案进行更改后,代码在API上运行

private File createImageFile() throws IOException {
    // Create an image file name
    String imageFileName = "myvideo";
    File storageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DCIM), "Camera");
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".mp4",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    Log.v("myTag","FAB create image");
    mCurrentPhotoPath = "file:" + image.getAbsolutePath();
    return image;
}

这是从下面的函数调用的:

public void startRecording()
{

    Log.v("myTag","FAB recording");
    File mediaFile = null;
    try {
        mediaFile = createImageFile();
    } catch (IOException ex) {
        Log.v("myTag","Exception");
        return;
    }


    Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT,5);
    //fileUri = Uri.fromFile(mediaFile);
    fileUri = FileProvider.getUriForFile(PlayHelpVideo.this,
            BuildConfig.APPLICATION_ID + ".provider",
            mediaFile);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
    startActivityForResult(intent, VIDEO_CAPTURE);
}

共有1个答案

欧阳嘉年
2023-03-14

您可以使用FileProvider类来访问特定的文件或文件夹,使其他应用程序可以访问这些文件或文件夹。创建您自己的继承文件提供者的类,以确保您的文件提供者不会与此处所述的导入依赖项中声明的文件提供者冲突。

file://URI替换为内容://URI的步骤:

添加扩展FileProvider的类

public class GenericFileProvider extends FileProvider {}

添加文件提供者

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <application
        ...
        <provider
            android:name=".GenericFileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest>

然后创建提供者路径。xml文件夹中的文件。如果文件夹不存在,则可能需要创建该文件夹。文件内容如下所示。它描述了我们希望以External_files的名称共享对根文件夹(path=“.”)中外部存储的访问。

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

最后一步是更改下面的代码行

fileUri = Uri.fromFile(mediaFile);

fileUri= FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", mediaFile);

 类似资料:
  • 你如何通过调用Android camera应用程序捕捉视频,使用4.3中的意图。我让它在4.2及以下版本工作。就连谷歌的样本也坏了。这是虫子吗?或者谷歌改变了他们返回录制视频的方式。图像捕捉仍然有效。 我仍然返回一个RESULT_OK,但是intent数据在mediastore.action_video_capture intents上为空。

  • 问题内容: 我已经创建了一个将捕获图片并保存在sdcard文件夹中的android应用程序,现在我想使用自定义名称保存图片。 这是我用来捕获图像并将其保存在sd卡文件夹中的代码,请帮助我以特定名称保存图像,例如:android.jpeg 问题答案: 您还需要在Android清单中添加权限。 该代码段将使用名称保存内部内容

  • 嗨,我一直在尝试使用意图从Nougat 7.0录制和保存视频,我可以录制视频,但不会保存在设备存储中。我甚至使用来避免“FileUriExposedException”。但是当涉及捕获图像时,它会保存在下面指定的路径中。这是我的代码。 上述代码适用于所有牛轧糖前版本。谁能为我提供一个更好的解决方案来录制视频并保存在设备存储中。

  • 本文向大家介绍在MongoDB中如何获取保存的对象?,包括了在MongoDB中如何获取保存的对象?的使用技巧和注意事项,需要的朋友参考一下 让我们首先创建一个变量。以下是查询- 以下是使用save()保存记录的查询- 在find()方法的帮助下显示集合中的所有文档- 这将产生以下输出-

  • 我能够创建并开始拍摄视频。但是如何设置文件名并将其保存到特定目录? 这是我到目前为止所拥有的: