cordova-plugin-file
cordova-plugin-file copied to clipboard
FileReader.readAs*(file) returns null onloadend
Bug Report
FileReader.readAs*(file) returns null in this.result and has FileError with code: 1 (not found) with video file.
Problem
The exact same code works fine on iOS, however I can't get it to work on Android.
Information
The command below will make it easier to understand what I'm trying to do.
Code
This is already set
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap:">
Actual code
async captureVideoErrorOnAndroid() {
const printError = (e) => console.log(e);
navigator.device.capture.captureVideo(function(mediaFiles) {
const mediaFile = mediaFiles[0];
console.log(`capture: Got media file: ${JSON.stringify(mediaFile)}`);
// note, on iOS I have to use media.localURL rather than media.fullPath
// I also tried media.localURL on Android, but the results are the same
window.resolveLocalFileSystemURL(mediaFile.fullPath, function(fileEntry){
console.log(`capture: Got fileEntry: ${JSON.stringify(fileEntry)}`);
fileEntry.file(function (file) {
console.log(`capture: Got file: ${JSON.stringify(file)} `);
const reader = new FileReader();
reader.onloadend = function() {
console.log(`capture: result: ${this.result}, error: ${JSON.stringify(this.error)}`);
};
reader.readAsArrayBuffer(file);
}, printError);
}, printError)
}, printError, {limit: 1, quality: 0, duration: 10})
}
Output for iOS (working just fine)
capture: Got media file: {"name":"58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV","localURL":"cdvfile://localhost/temporary/58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV","type":"video/quicktime","lastModified":null,"lastModifiedDate":1563995943708.5723,"size":87457,"start":0,"end":0,"fullPath":"/private/var/mobile/Containers/Data/Application/B8A6D1DC-72B7-4F8C-A106-A137E358E0AA/tmp/58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV"} (cordova.js, line 1732)
capture: Got fileEntry: {"isFile":true,"isDirectory":false,"name":"58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV","fullPath":"/58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV","filesystem":"<FileSystem: temporary>","nativeURL":"file:///var/mobile/Containers/Data/Application/B8A6D1DC-72B7-4F8C-A106-A137E358E0AA/tmp/58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV"} (cordova.js, line 1732)
capture: Got file: {"name":"58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV","localURL":"cdvfile://localhost/temporary/58568874201__E85C0792-08F4-4652-9776-9E0815101786.MOV","type":"video/quicktime","lastModified":1563995943708.5723,"lastModifiedDate":1563995943708.5723,"size":87457,"start":0,"end":87457} (cordova.js, line 1732)
capture: result: [object ArrayBuffer], error: null (cordova.js, line 1732)
Output for Android (with result being null)
capture: Got media file: {"name":"VID_20190725_030555.3gp","localURL":"cdvfile://localhost/sdcard/DCIM/Camera/VID_20190725_030555.3gp","type":"video/3gpp","lastModified":null,"lastModifiedDate":1563995159000,"size":75157,"start":0,"end":0,"fullPath":"file:///storage/emulated/0/DCIM/Camera/VID_20190725_030555.3gp"}
capture: Got fileEntry: {"isFile":true,"isDirectory":false,"name":"VID_20190725_030555.3gp","fullPath":"/DCIM/Camera/VID_20190725_030555.3gp","filesystem":"<FileSystem: sdcard>","nativeURL":"file:///storage/emulated/0/DCIM/Camera/VID_20190725_030555.3gp"}
capture: Got file: {"name":"VID_20190725_030555.3gp","localURL":"cdvfile://localhost/sdcard/DCIM/Camera/VID_20190725_030555.3gp","type":"video/3gpp","lastModified":1563995159000,"lastModifiedDate":1563995159000,"size":75157,"start":0,"end":75157}
capture: result: null, error: {"code":1}
Platform
Android 8.0.0
Version information
Cordova 8.1.2 cordova-plugin-file 6.0.2
Checklist
- [x] I searched for existing GitHub issues
- [x] I updated all Cordova tooling to most recent version
- [x] I included all the necessary information above
This may resolve https://github.com/apache/cordova-plugin-media-capture/issues/135
I second this issue. The solution provided in #135 doesn't seem to fix the read file issue.
I created a sample app logging the issue here.
@janpio any chance you can take a quick look at the repo linked by @eduardoewgo (sorry, I just grabbed your username from the contributors page)? We're trying to understand if the issue is with cordova-plugin-media-capture, cordova-plugin-file, or something else. We've spent a good deal of time attempting to resolve this on our own and we're not sure what the issue could be.
If there's anything we can do to more clearly define the issue, please let me know. Or, if you think there's another person that might be able to help move this forward, would you mention them here?
Never mind, looks like the issue was related to the way permissions are requested in the capture media plugin. In captureVideo, it didn't ask for the permissions needed to actually get the contents of the file after capturing it.
What would be the additional permissions needed?
Here's a link to the PR: https://github.com/apache/cordova-plugin-media-capture/pull/147/files
The issue was that the READ_EXTERNAL_STORAGE permission was not requested. Maybe there's another way to do it, but the update I made to captureVideo seems to be in line with the way captureImage works.
Thanks so much for finding that!
Potentially related to https://github.com/apache/cordova-plugin-file/issues/350 (both dealing with sdcard
external storage)
Any updates on this?
I am just trying to use it (with Ionic) to get files from any Android folders (WhatsApp, Documents, etc), but it always returns null, even using other methods like readAsText, readAsDataURL or the readAsArrayBuffer. Follow my config:
Ionic:
Ionic CLI : 5.4.15 Ionic Framework : @ionic/angular 5.2.2 @angular-devkit/build-angular : 0.901.9 @angular-devkit/schematics : 9.1.9 @angular/cli : 9.1.9 @ionic/angular-toolkit : 2.2.0
Cordova:
Cordova CLI : 9.0.0 ([email protected]) Cordova Platforms : android 8.1.0 Cordova Plugins : cordova-plugin-file: 6.0.2 cordova-plugin-file-opener2: 3.0.4 cordova-plugin-filechooser: 1.2.0 cordova-plugin-filepath": 1.5.8
The code that fails is:
async openFiles() {
this.fileChooser
.open()
.then(contentPath => {
const that = this;
this.filePath.resolveNativePath(contentPath).then(uri => {
const lastSeparator = uri.lastIndexOf('/');
const fileName = uri.substr(lastSeparator + 1);
const sysPath = uri.substr(0, lastSeparator);
that.file.readAsArrayBuffer(sysPath, fileName).then(buff => {
// buff is always null
const blob = new Blob([new Uint8Array(buff)], { type: 'image/jpg' });
});
});
});
}
Adding ' android:requestLegacyExternalStorage="true"' to AndroidManifest.xml solves the problem.
Read more at https://developer.android.com/training/data-storage/use-cases.