androidcordovacordova-plugin-file

Cordova Android FileReader.readAsDataURL NOT_FOUND_ERR


I am using both cordova-plugin-file and cordova-plugin-media-capture to capture video on iOS and Android. This implementation works perfectly on iOS, but does not on Android. I've traced the issue to the FileReader instance not being able to find the file that cordova-plugin-media-capture has recorded. Here is the block of code:

if (navigator && navigator.device.capture && window.cordova.file) {
    navigator.device.capture.captureVideo((mediaFiles: MediaFile[]) => {
        if (mediaFiles.length > 0) {
            const mediaFile = mediaFiles[0];
            const type = mediaFile.type;
            window.resolveLocalFileSystemURL((mediaFile as any).localURL, (fileEntry: Entry) => {
                (fileEntry as FileEntry).file((file: File) => {
                    // "file" is a valid file with a local URL (cdvfile://localhost/sdcard/DCIM/....)
                    const fileReader = new FileReader();
                    fileReader.onloadend = (event: ProgressEvent) => {
                        console.log(event);
                        // event.target.error = 1 here which according to the docs is NOT_FOUND_ERR
                        success({ data: (event.target as any).result, type });
                    };
                    fileReader.readAsDataURL(file);
                }, (_error: FileError) => {
                    console.log(_error);
                });
            }, (_error: FileError) => {
                console.log(_error);
            });
        }
    }, (_error: CaptureError) => {
        console.log(_error);
    }, { limit: 1, duration: 10, quality: 1 });
}

Any ideas on what could be causing this? Here are the things I've tried:

  1. Added <preference name="AndroidPersistentFileLocation" value="Compatibility" /> to config.xml. Removed after this approach didn't work.
  2. Added <access origin="cdvfile://*"/> to config.xml. Removed after this didn't work.
  3. Ensured CSP includes cdvfile:
  4. Ensured AndroidManifest.xml has both android.permission.WRITE_EXTERNAL_STORAGE and android.permission.READ_EXTERNAL_STORAGE
  5. Validated that the videos do in fact exist on the phone by browsing the Files app. The videos play just fine.

Testing on Android 8 with a Moto G6.

Thanks in advance.


Solution

  • After debugging cordova-plugin-file, I discovered that the reported NOT_FOUND_ERR was misleading, because it turns out there was a permissions issue.

    cordova-plugin-file error

    I thought it was sufficient to put the permissions to read external storage in the manifest, but it isn't. Android requires runtime permissions: https://developer.android.com/training/permissions/requesting.html

    After adding runtime permissions, the video capture process works as expected.