19

We're using MediaRecorder to record video to a file on the external storage using setOutputFile() before doing the actual recording.

Everything works fine, but the main issue is that as soon as the recording is done, we want to start playing the recorded video back in a VideoView.

How to know when the file is ready to be read and played back?

Suragch
  • 364,799
  • 232
  • 1,155
  • 1,198
Stefan H Singer
  • 5,304
  • 2
  • 23
  • 26

6 Answers6

20

The FileObserver class suits your needs perfectly. Here is the documentation. It's easy to use. When a observed file is closed after writing, the onEvent callback is called with CLOSE_WRITE as the parameter.

MyFileObserver fb = new MyFileObserver(mediaFile_path, FileObserver.CLOSE_WRITE);
fb.startWatching();

class MyFileObserver extends FileObserver {

    public MyFileObserver (String path, int mask) {
        super(path, mask);
    }

    public void onEvent(int event, String path) {
        // start playing
    }
}

Don't forget to call stopWatching().

halfer
  • 18,701
  • 13
  • 79
  • 158
Ronnie
  • 23,807
  • 8
  • 52
  • 93
  • I'm not able to test this right now, but do you know if it's guaranteed that the MediaRecorder doesn't close the file between writes? – Stefan H Singer Sep 24 '11 at 12:03
  • Not aware of that. But even if it does, you can maintain the recording state in a member and check on it in `onEvent`. If recording is paused, just ignore the event. – Ronnie Sep 24 '11 at 12:28
  • 5
    A gotcha when using `FileObserver` is that it does not work as advertised. Rather than monitor an individual file, it monitors a directory. Therefore, monitor the directory for changes. In `onEvent(int event, String path)` the path to the actual file affected will be passed as the `String` parameter. You can then compare that path with the path to your file of interest and respond accordingly. See http://stackoverflow.com/questions/16448002/android-fileobserver-monitors-only-top-directory for more information. – Tash Pemhiwa Aug 25 '14 at 06:36
  • I would advice against using FileObserver, it does not work with all versions. You can read more about it here https://issuetracker.google.com/issues/37065227 – OneBigQuestion Sep 13 '17 at 13:30
5

We solved similar problem with the following algo:

while (file not complete)
    sleep for 1 sec
    read the fourth byte of the file
    if it is not 0 (contains 'f' of the 'ftyp' header) then
        file is complete, break

The key point is that MediaRecorder writes the ftyp box at the very last moment. If it is in place, then the file is complete.

Ash
  • 1,621
  • 13
  • 17
2

In my tests irrespective of the size of the recording mediaRecorder.stop() is a blocking method that only returns after the file has been completely written and closed by the media recorder.

So JPMs answer is actually correct.

You can verify this by calling File.length() immediately after stop(). You will find that the output file length is the final length of the file at this point. In other words media recorder does not write anything further to the file after stop() has returned.

Sani Elfishawy
  • 653
  • 1
  • 7
  • 14
1

I haven't tried this myself but this might work:

public void release () Since: API Level 1

Releases resources associated with this MediaRecorder object. It is good practice to call this method when you're done using the MediaRecorder.

If it does what it says, then I guess if you call this and after this method returns you know the file is ready.

Caner
  • 49,709
  • 33
  • 153
  • 169
  • Really? I thought that was just for releasing resources and letting the GC deal with them, also, we record many clips so reconstructing the MediaRecorder each time would probably hurt performance for us. I'll investigate it further though, thanks! – Stefan H Singer Sep 20 '11 at 08:45
0

Apparently there is no way to detect when the recording has stopped in Media player, but there is a stop() that you can override if you create a custom class that implements MediaRecorder. here I would do something like this:

public class MyRecorder implements MediaRecorder {
    public boolean stopped;

    .... implement all the methods that MediaRecorder has making 
         sure to call super for each method.

    @Override
    public void myStop() {
        this.stopped = true;
        super.stop(); 
    }
}

Then you can access the boolean to see if it has stopped recording.

JPM
  • 8,360
  • 13
  • 73
  • 124
  • 1
    But when the recording is stopped, more data has to get written to the storage and we can't start playing the video until the recording really has gotten written to storage. – Stefan H Singer Sep 15 '11 at 07:33
  • What has to get written? If its custom what you are writing then call your custom function from inside the overridden stop method then set the stopped variable after your call. – JPM Sep 15 '11 at 14:57
  • 2
    I know when we _stop_ the recording. When the recording gets stopped, the recorder writes data to disk and I want to know when it has finished writing data :) – Stefan H Singer Sep 16 '11 at 09:05
0

A dirty way would be to check the lastModified() value of the File and open the VideoView if the File wasn't modified for 2 seconds.

Franziskus Karsunke
  • 4,470
  • 1
  • 36
  • 52
  • We've already got hacks in place, but I'd prefer a proper solution if there is one. If there's none, well, then we'll just keep using our hack and add some error safeguarding to it :) – Stefan H Singer Sep 18 '11 at 10:53