1

I have an app which records videos, it has about 80K current installations (more than 100K downloads), Crashlytics statistics seems to be good - Crash-free users 99.66% and rating on Google Play is also OK - 4.5

But still for some of my users can happen the next error (it may happened for each user once or a couple of times by now, so not often, but still happens from time to time):

java.io.FileNotFoundException: /storage/7886-1D16/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-18 21h 18m 06s.mp4: open failed: EROFS ... blah blah blah ... android.media.MediaRecorder.prepare(MediaRecorder.java:1028)

Here's the code (similar to real one in my project), as you can see before mediaRecorder.prepare() and video recording I check if output directory is good, if File.canWrite() returns true then it means that files exists, app has needed permission to write at this path and storage is mounted https://developer.android.com/reference/java/io/File#canWrite()

// canWrite() - means that file exists and app is allowed to write
if (outputFolderFile.canWrite()) {
    // directory is OK, Android says that there is nothing wrong...
    
    val videoFile = File(outputFolderFile, videoFileName)
    
    ... // MediaRecorder settings
    
    mediaRecorder.setOutputFile(videoFile.absolutePath)
    
    ... // other MediaRecorder settings
    
    try {
        mediaRecorder.prepare() // FileNotFoundException here from time to time
    } catch (e: Exception) {
        e.printStackTrace()
        
        openReportErrorDialog(e)
    }
}

Additionally I was trying to add && Environment.getExternalStorageState(outputFolderFile).equals(Environment.MEDIA_MOUNTED)) or || (outputFolderFile.mkdirs() && outputFolderFile.canWrite()) to that condition (outputFolderFile.canWrite()) but it doesn't matter, error still happens

I also was trying to add createNewFile(videoFile ) line before mediaRecorder.prepare() but doesn't help and in this case the error is java.io.IOException: No such file or directory, java.io.IOException: No such file or directory at java.io.UnixFileSystem.createFileExclusively0(Native Method)

So Android says that directory exists, everything is ok and app can write files there but...

Here I almost added all reports from my users about this error:

HUAWEI CAG-L22
java.io.FileNotFoundException: /storage/7886-1D16/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-18 21h 18m 06s.mp4: open failed: EROFS (Read-only file system)

HUAWEI FIG-LX1
java.io.FileNotFoundException: /storage/5309-1D08/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-04-10/2021-04-10 10h 17m 18s.mp4: open failed: EROFS (Read-only file system)

LGE LG-K350
java.io.FileNotFoundException: /storage/4CA1-71F9/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-04-02/2021-04-02 14h 53m 31s.mp4: open failed: ENOENT (No such file or directory)

LGE LM-K300
java.io.FileNotFoundException: /storage/C5F6-15E4/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-06/2021-03-06 02h 26m 40s PM.mp4: open failed: ENOENT (No such file or directory)
 
LGE LM-X420
java.io.FileNotFoundException: /storage/B15A-170A/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-02-12/2021-02-12 13h 31m 42s.mp4: open failed: ENOENT (No such file or directory)

OPPO CPH1931
java.io.FileNotFoundException: /storage/02EB-1B18/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-13/2021-03-13 12h 15m 30s.mp4: open failed: EROFS (Read-only file system)

Prestigio PMT3257_3G
java.io.FileNotFoundException: /storage/emulated/0/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-04-10/2021-04-10 10h 32m 21s.mp4: open failed: ENOENT (No such file or directory),

samsung SM-G900F
java.io.FileNotFoundException: /storage/161A-0B3C/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-02/2021-03-02 08h 06m 33s.mp4: open failed: ENOENT (No such file or directory)

samsung SM-N960W
java.io.FileNotFoundException: /storage/2A2C-40A4/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-04-14/2021-04-14 02h 35m 45s AM.mp4: open failed: ENOENT (No such file or directory)

Xiaomi M2004J19C
java.io.FileNotFoundException: /storage/emulated/0/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-11 11h 09m 18s AM.mp4: open failed: ENOENT (No such file or directory)

Xiaomi M2007J20CG
java.io.FileNotFoundException: /storage/82AD-49E3/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-04-06/2021-04-06 06h 51m 14s.mp4: open failed: ENOENT (No such file or directory)

Xiaomi M2007J3SG
java.io.FileNotFoundException: /storage/emulated/0/Movies/MY_APP_NAME_HERE/2021-03-31/2021-03-31 15h 39m 27s.mp4: open failed: EPERM (Operation not permitted)

Xiaomi M2007J3SY
java.io.FileNotFoundException: /storage/emulated/0/Movies/MY_APP_NAME_HERE/2021-04-10/2021-04-10 01h 30m 42s PM.mp4: open failed: EPERM (Operation not permitted)

Xiaomi M2102J20SG
java.io.FileNotFoundException: /storage/emulated/0/Movies/MY_APP_NAME_HERE/2021-04-17/2021-04-17 16h 16m 59s.mp4: open failed: EPERM (Operation not permitted)

Xiaomi POCO F2 Pro
java.io.FileNotFoundException: /storage/emulated/0/Movies/MY_APP_NAME_HERE/2021-02-05/2021-02-05 19h 20m 36s.mp4: open failed: EPERM (Operation not permitted)

Xiaomi Redmi 5A
java.io.FileNotFoundException: /storage/577D-D95B/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-13/2021-03-13 16h 33m 21s.mp4: open failed: EROFS (Read-only file system)

Xiaomi Redmi 7A
java.io.FileNotFoundException: /storage/4DC6-1515/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-03-12/2021-03-12 09h 18m 35s.mp4: open failed: EIO (I/O error)

Xiaomi Redmi Note 8T
java.io.FileNotFoundException: /storage/A018-ED55/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-02-06/2021-02-06 17h 29m 59s.mp4: open failed: EIO (I/O error)

ZTE A2017G
java.io.FileNotFoundException: /storage/emulated/0/Movies/MY_APP_NAME_HERE/2021-03-26/2021-03-26 08h 27m 42s.mp4: open failed: ENOENT (No such file or directory)

So it mostly happens for Xiaomi devices, and mostly when recording to external micro SD Card (e.g. path is /storage/2A2C-40A4/***), though for built-in storage of phone (/storage/emulated/0/***) it also happens sometimes...

Versions of Android are different, from 6 (old) to 11 (newest), so it doesn't matter.

You can see that error is similar (starting with FileNotFoundException and file absolute path) but sometimes it changes at the end between

  • open failed: EROFS (Read-only file system)
  • open failed: ENOENT (No such file or directory)
  • open failed: EIO (I/O error)
  • open failed: EPERM (Operation not permitted)

Of course users don't send such error report everyday but still it happens often.

I don't have any idea why it happens. I can't reproduce this issue on my own devices (two Samsung, one Lenovo, one Huawei and one Xiaomi devices).

Maybe it happens because read/write time to storage was very slow or freezed (heavy load on it storage controller) at this point and Android (MediaRecorder) could not create an output video file for recording?

Any ideas or solutions?

p.s. full example of error:

java.io.FileNotFoundException: /storage/5309-1D08/Android/media/MY_APP_PACKAGE_NAME_HERE/2021-04-10/2021-04-10 10h 17m 20s.mp4: open failed: EROFS (Read-only file system) at libcore.io.IoBridge.open(IoBridge.java:485) at java.io.RandomAccessFile.(RandomAccessFile.java:288) at java.io.RandomAccessFile.(RandomAccessFile.java:151) at android.hsm.HwMediaPermWrapper.setOutputFile(HwMediaPermWrapper.java:127) at android.media.MediaRecorder.prepare(MediaRecorder.java:1028)

user924
  • 8,146
  • 7
  • 57
  • 139
  • I don't know where you are getting `outputFolderFile` from. You are not going to be able to reliably write to arbitrary paths on removable storage on Android 4.4+. By default, you are not going to be able to write to any of the locations cited in your list on Android 10+. And, your only workaround for those (`android:requestLegacyExternalStorage="true"`) is going away as an option in the very near term for Android 11+. Since it appears that you are working with media, perhaps you could switch to using `MediaStore` on Android 10+. – CommonsWare Apr 17 '21 at 18:49
  • @CommonsWare but `/storage/emulated/0` is not removable storage (for built-in phone memory this error also happens), `/storage/577D-D95B/` is removable storage sd card. I get paths by `Context.externalMediaDirs` (returns one path if devices doesn't have removable sd card or two if has) plus `Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)` (shared movies folder). Before recording I check if storage is mounted and I can write at this path. I know about `MediaStore`, but it's from 29 API, many devices on Android < 10 and still error on them – user924 Apr 17 '21 at 19:00
  • @CommonsWare also on Android 10 and 11 we need to use `MediaStore` and `setOutputFile(fileDescriptor)` (from `Uri`) only when recording at shared MOVIES or DCIM folders (e.g. `Environment.DIRECTORY_MOVIES`), we can still use `setOutputFile(stringPath)` when recording at folder of `Context.externalMediaDirs`. Also we can even record to shared folder on Android 10/11 also with `setOutputFile(stringPath)` if you create recorder folder by app at shared folder and it will be writeable (`it.canWrite()` `true`), so we can skip `MediaStore` even for Android 11 – user924 Apr 17 '21 at 19:09
  • "Before recording I check if storage is mounted and I can write at this path" -- I have long been skeptical about "can write at this path" logic, as `canWrite()` has never seemed reliable based on other complaints lodged at this site. In your case, recording a video will take a lot more time than will, say, saving an image. Do you have any idea whether your errors are coming at the start (suggesting lack of access) or after the recording has been going for a while (suggesting low-level I/O problems)? – CommonsWare Apr 17 '21 at 19:09
  • "we can still use setOutputFile(stringPath) when recording at folder of Context.externalMediaDirs" -- agreed. I had missed that your paths would have been from `getExternalMediaDirs()`, and I apologize for that mistake. Your locations *ought* to be OK in general. Another thing you could try, rather than relying on `canWrite()`, is to write something small yourself (e.g., a few bytes) and try to read it back, before you try getting `MediaRecorder` to record things. – CommonsWare Apr 17 '21 at 19:13
  • @CommonsWare I also thought about when this error happens, I think it happens after the recording has been going for a while, for example, was recording for 1 hour, each video file duration, e.g. is 10 minutes, and after stopping previous recording then app starts a new recording automatically and error happens. I can try to ask this info from my users. – user924 Apr 17 '21 at 19:19
  • 1
    @CommonsWare and I have an idea to add some logic for re-trying starting a new recording in this case, e.g. if recorder `prepare()` method fails then I can make a delay 500 or 1000 ms and try again, e.g. maximum 1-3 times, if every attempt fails, then I will show recording start error to a user (UI) – user924 Apr 17 '21 at 19:21
  • 1
    Bear in mind that the process writing to disk in the `MediaRecorder` case is not your process, but rather an OS process associated with the media subsystem. So, even if your own code is perfectly fine, you might run into problems if that media process encounters bugs. I also have not tested to see what sorts of exceptions are triggered from running out of disk space. I think your retry policy is worth a shot. And if you are correct about the timing of the problem, this is not an access control issue, as you would be failing right away, not after having recorded for a while. – CommonsWare Apr 17 '21 at 19:23
  • 1
    @CommonsWare ok, thank you so much for your time. Then I will try this logic. If it will help (e.g. it will be a month without such issues after on the newest version of app) then I will report here, will be a good info for other developers – user924 Apr 17 '21 at 19:26
  • I think this will solve your problem https://stackoverflow.com/a/37819897/15394749 – محمد هشام Jul 20 '21 at 02:30
  • @محمدهشام no!... – user924 Jul 21 '21 at 16:33

0 Answers0