cordova-plugin-file-transfer
cordova-plugin-file-transfer copied to clipboard
`download` method failing on cordova / android platform with `java.lang.NullPointerException` exception
Hi !
I'm currently unable to make the plugin work properly.
FileTransfer.download
is failing with an error code 3 (FileTransferError.CONNECTION_ERR
) and an exception java.lang.NullPointerException
.
Minimal example
cordova create . com.example.my_app "My App"
cordova platform add android
cordova plugin add cordova-plugin-file-transfer
Add this child to the widget
element in config.xml
.
<access origin="*" />
Add a call to the demo
function below from within onDeviceReady
.
function demo() {
window.requestFileSystem(window.PERSISTENT, 5 * 1024 * 1024,
fs => fs.root.getFile('cordova_bot.png', { create: true, exclusive: false },
fileEntry => ft_approach(fileEntry),
error => console.log(`file creation error: ${error}`)
),
(error) => console.log(`fs loading error: ${error}`)
);
}
function ft_approach(fileEntry) {
const fileTransfer = new FileTransfer();
fileTransfer.download(
'https://cordova.apache.org/static/img/cordova_bot.png',
fileEntry.toURL(),
() => window.alert('download complete'),
error => console.log(`download error: ${JSON.stringify(error, undefined, 2)}`),
false,
);
}
Run the app on the Android Studio emulator
and attach Chrome DevTools .
The output should be something like:
download error: {
"code": 3,
"source": "https://cordova.apache.org/static/img/cordova_bot.png",
"target": "https://localhost/__cdvfile_persistent__/cordova_bot.png",
"http_status": 200,
"body": null,
"exception": "java.lang.NullPointerException"
}
Workaround
Using web APIs.
Replacing ft_approach
with the xhr_approach
function below works, although not idea for large files.
function xhr_approach(fileEntry) {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://cordova.apache.org/static/img/cordova_bot.png', true);
xhr.responseType = 'blob';
xhr.onload = function () {
const blob = xhr.response;
if (xhr.status != 200) {
console.error(`request error ${xhr.status}: ${xhr.statusText}`);
return;
}
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = () => window.alert('download complete');
fileWriter.onerror = error => console.log(`file writing error: ${error}`);
fileWriter.write(blob);
});
};
xhr.onerror = function() {
console.log('request error')
}
xhr.send();
}
Note: Update CSP accordingly
<meta http-equiv="Content-Security-Policy" content="default-src https://cordova.apache.org ...">
Versions
Windows 10 Home
Node 18.17.1
Cordova 12.0.0
cordova-android 12.0.1
cordova-plugin-file 8.0.0
cordova-plugin-file-transfer 2.0.0
Android SDK 33
Gradle 8.3
@the-other-sunny, Hello, did you find any solution?
@the-other-sunny, Hello, did you find any solution?
the xhr approach ^^
@the-other-sunny can you explain it a bit more, may be with some code. I am facing the same issue
Hello, I got the same error
03-25 23:08:57.066 29040 29835 E FileTransfer: {"code":3,"source":"https:\/\/XXXX","target":"cdvfile:\/\/localhost\/persistent\/path\/to\/file.txt","http_status":200,"exception":"java.lang.NullPointerException"}
03-25 23:08:56.746 29040 29835 E FileTransfer: java.lang.NullPointerException
03-25 23:08:56.746 29040 29835 E FileTransfer: at java.io.FileOutputStream.<init>(FileOutputStream.java:227)
03-25 23:08:56.746 29040 29835 E FileTransfer: at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
03-25 23:08:56.746 29040 29835 E FileTransfer: at org.apache.cordova.filetransfer.FileTransfer$2.run(FileTransfer.java:796)
03-25 23:08:56.746 29040 29835 E FileTransfer: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
03-25 23:08:56.746 29040 29835 E FileTransfer: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
did someone find a solution ?
I'm on cordova-android 12
Regards Louis
@anubhavs19 @lchanouha
I presented a workaround in my initial message which is to use the browser/webview's XMLHttpRequest
API.
I'm sorry but I'm not aware of a native solution and also not well versed in cordova
.
Hi,
the following code is not working on Android..
var example_external_file = "https://cordova.apache.org/static/img/cordova_bot.png"
window.requestFileSystem(window.PERSISTENT, 128 * 1024 * 1024, function (fs) {
fs.root.getFile("cordova_bot.png", {create: true}, function (fileEntry) {
var target = fileEntry.toURL();
cordova.fileTransfer.download(example_external_file, target, function (success) {
console.log('success', success);
}, function (err) {
console.log('error', err);
})
});
});
err is:
err = {
body: null,
code: 3,
exception: "java.lang.NullPointerException",
http_status: 200,
source: "https://cordova.apache.org/static/img/cordova_bot.png",
target: "https://localhost/__cdvfile_persistent__/cordova_bot.png"
};
the problem is the target path. is should be something with file:// and not https:// the problem maybe lies here https://github.com/apache/cordova-plugin-file/issues/619
With https:// fails this code in Cordova-Plugin-File
file = resourceApi.mapUriToFile(targetUri);
targetUri = "https://localhost/cdvfile_persistent/cordova_bot.png" file = NULL
and file=NULL leads to java.lang.NullPointerException
Quickfix: fileEntry.toURL() returns: "https://localhost/cdvfile_persistent/cordova_bot.png" -> wrong
fileEntry.toNativeURL() also returns: "https://localhost/cdvfile_persistent/cordova_bot.png" -> wrong
fileEntry.nativeUrl is "file:///data/user/0/de.fuf.corodva-app/files/files/cordova_bot.png" -> fine
Workaround: use fileEntry.nativeUrl instead of fileEntry.toUrl() as target in cordova.fileTransfer.download(source, target)
Code with workaround:
window.quirksMode = false;
function download_file(source, fileEntry, onSuccess, onError) {
var target = fileEntry.toURL();
// if quirksMode is enabled, use the nativeURL instead of fileEntry.toURL
if (window.quirksMode) {
target = fileEntry.nativeURL;
}
cordova.fileTransfer.download(source, target, onSuccess, function (err) {
// only if the error appears and quirksMode is false
if (err.code === 3 && window.quirksMode === false) {
// enable quirksMode
window.quirksMode = true;
console.log('error', err, '-> enabling quirksMode')
// and try to redownload the file..
download_file(source, fileEntry, onSuccess, onError);
return;
}
onError(err);
});
}
window.requestFileSystem(window.PERSISTENT, 128 * 1024 * 1024, function (fs) {
fs.root.getFile("cordova_bot.png", {create: true}, function (fileEntry) {
download_file(example_external_file, fileEntry, function (succ) {
console.log("success", succ);
}, function (err) {
console.log("error", err);
});
});
});