Android 将视频保存到文件

Android saving a video to a file

我正在设计一个具有媒体功能的应用程序,其中之一是视频捕获。我正在使用对相机的默认调用,而不是创建我自己的相机。我遇到的问题是,在拍摄视频后,它不会保存到我指定的视频文件中,但到目前为止,我测试过的这个问题只发生在三星 phones 使用相机应用程序的情况下。如果我在三星 phone 或另一家公司的 phone 上使用 Google 相机,效果很好。这是三星 phones 的已知错误还是我只是做错了什么?如果是,是否有解决方法?

这是我的视频处理器。

private void videoHandler() {
    Intent intent = new Intent( MediaStore.ACTION_VIDEO_CAPTURE );
    if ( intent.resolveActivity( getPackageManager() ) != null ) {
        File videoFile = null;
        try {
            videoFile = createVideoFile();
        } catch ( IOException e ) {
            System.out.println( "Error creating file." );
        }

        if ( videoFile != null ) {
            videoUri = Uri.fromFile( videoFile );
            intent.putExtra( MediaStore.EXTRA_OUTPUT, videoUri );
            intent.putExtra( MediaStore.EXTRA_VIDEO_QUALITY, 1 );
            intent.putExtra( MediaStore.EXTRA_SIZE_LIMIT, 15000000L );
            intent.putExtra( MediaStore.EXTRA_DURATION_LIMIT, 6 );
            startActivityForResult( intent, VIDEO_REQUEST_CODE );
        }
    }
}

它调用 createVideoFile,我在其中为目标预先创建了一个视频文件。

private File createVideoFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat( "yyyyMMdd_HHmmss" ).format( new Date() );
    String imageFileName = "MP4_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES );
    File video = File.createTempFile(
            imageFileName,  /* prefix */
            ".mp4",         /* suffix */
            storageDir      /* directory */
    );

    this.videoUri = Uri.fromFile( video );
    Intent mediaScanIntent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE );
    mediaScanIntent.setData( this.videoUri );
    this.sendBroadcast( mediaScanIntent );
    return video;
}

这是我尝试在我的 onActivityResult 中调用 videouri 时遇到的错误。

01-17 16:37:23.254  27162-28145/com.example.kevinem.blitz E/ImageLoader﹕ /storage/emulated/0/Pictures/MP4_20150117_163704_-918353230.mp4: open failed: ENOENT (No such file or directory)
java.io.FileNotFoundException: /storage/emulated/0/Pictures/MP4_20150117_163704_-918353230.mp4: open failed: ENOENT (No such file or directory)
        at libcore.io.IoBridge.open(IoBridge.java:409)
        at java.io.FileInputStream.<init>(FileInputStream.java:78)
        at java.io.FileInputStream.<init>(FileInputStream.java:105)
        at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStreamFromFile(BaseImageDownloader.java:160)
        at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStream(BaseImageDownloader.java:88)
        at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.getImageStream(BaseImageDecoder.java:93)
        at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.decode(BaseImageDecoder.java:73)
        at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.decodeImage(LoadAndDisplayImageTask.java:264)
        at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:237)
        at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:135)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)
 Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
        at libcore.io.Posix.open(Native Method)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
        at libcore.io.IoBridge.open(IoBridge.java:393)

您使用 File.createTempFile( ) 有什么特殊原因吗?

Creates an empty file in the default temporary-file directory, using the given prefix and suffix to generate its name. Invoking this method is equivalent to invoking createTempFile(prefix, suffix, null).

The Files.createTempFile method provides an alternative method to create an empty file in the temporary-file directory. Files created by that method may have more restrictive access permissions to files created by this method and so may be more suited to security-sensitive applications.

不确定这是否产生了预期的结果。我建议您查看此文档。

http://developer.android.com/reference/android/os/Environment.html#getExternalStoragePublicDirectory(java.lang.String)

尤其是这首曲子。

File path = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
return file.exists();

tl;dr

我想这会解决你的问题

 File video = new File(storageDir,  imageFileName + ".mp4")

我解决了我的问题。基本上我发现有人这么说。

There is no requirement that a camera app follow the rules of ACTION_IMAGE_CAPTURE or ACTION_VIDEO_CAPTURE. Some will honor a specific requested output location. Some will not, and will return where they chose to store the image/video in the Uri contained in the result Intent delivered on onActivityResult(). Some may be completely broken and not tell you anything about where the image/video was stored, even if there was one stored.

然后我在另一个post中发现我必须手动检索它。

if (resultCode == -1) {
        //create a MediaScanner to save the vid into the indicate path
        new MediaScannerConnectionClient() {
            private MediaScannerConnection msc = null;
            {
                msc = new MediaScannerConnection(
                        getApplicationContext(), this);
                msc.connect();
            }

            public void onMediaScannerConnected() {
                msc.scanFile(name_vid, null);
            }

            public void onScanCompleted(String path, Uri uri) {
                msc.disconnect();

            }
        };
        Toast.makeText(this,"Video saved succesfull",
                Toast.LENGTH_SHORT).show();
}

name_vid是你要保存字符串格式文件的路径。