Samuele B.
Samuele B.

Reputation: 658

Android - VideoView unable to play video in external storage

Inside of a fragment in my android application, I take a video using an intent and then save it to my external storage:

private void dispatchTakeVideoIntent() {
        Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        if (takeVideoIntent.resolveActivity(getActivity().getPackageManager()) != null) {
            startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
        }
    }

 @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
        if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == Activity.RESULT_OK) {

            takenVideoUri = intent.getData();

            String ext = ".mp4";
            String filename = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss.SSS")
                            .format(System.currentTimeMillis()) + ext;

                    File root = getContext().getExternalFilesDir(Environment.DIRECTORY_MOVIES);
                    File file = new File(root, filename);
                    try(
                        InputStream is = getContext().getContentResolver().openInputStream(takenVideoUri);
                        FileOutputStream fos =  new FileOutputStream(file)
                    ) {
                        BufferedOutputStream bos = new BufferedOutputStream(fos);
                        byte[] buf = new byte[1024];
                        while(is.read(buf)!=-1) {
                            bos.write(buf);
                        }
                        bos.close();
                        fos.close();
                        videoUri = Uri.fromFile(file);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    }
}

Then, inside of another fragment, I have a VideoView to which I want to pass the Uri of the saved video for it to play it.

Uri videoUri = /* gotten from the other fragment */
videoView.setVideoURI(videoUri);

However, when I open that fragment, I get the errors:

2022-04-28 18:53:59.273 23764-23821/my.app E/MediaPlayerNative: error (1, -2147483648)
2022-04-28 18:53:59.305 23764-23764/my.app E/MediaPlayer: Error (1,-2147483648)

I understand those are generic errors, which makes it worse because I have no clue as to where the error is.

My manifest file does include permission for both reading and writing external storage. I have tried saving the video to internal storage too, but nothing changed.

What am I doing wrong?

Upvotes: 0

Views: 264

Answers (1)

Crispert
Crispert

Reputation: 1167

It seems to me the file is incomplete/empty. You could check its size using file.length() before trying to play it. Copying the file might be unnecessary as you could simply call takeVideoIntent.putExtra(EXTRA_OUTPUT, uri) to the intent to specify the path(uri) the captured video's location.

What usually happens with camera capture outputs is that onActivityResult is called before the file contents were properly written to storage (bytes flushed and file closed) especially with slower storages (sd cards) so what you get is an incomplete file (often times even empty).

You can delay video playing after onActivityResult while checking if the video file's size and last modified time (file.lastModified()) have increased to see if writing/flushing has actually finished and you can play it. If it's a long video (more than a few seconds) and depending on the enconding used you may start playing it before its fully written to storage but if the video player reaches the end before the recording app has finished writing the playing will end abruptly and you'll probably need to reload the video in the player.

It's a big problem of linux with the slow writing on (ex/V)FAT partitions which are used on portable storage for interoperability with other OSs (Windows) especially over USB. It's always a long wait to copy a few GB of data on a USB stick.

Upvotes: 1

Related Questions