Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

download method failing on cordova / android platform with java.lang.NullPointerException exception #374

Open
the-other-sunny opened this issue Sep 14, 2023 · 6 comments

Comments

@the-other-sunny
Copy link

the-other-sunny commented Sep 14, 2023

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 the-other-sunny changed the title download method failing on cordova / android platform with java.lang.NullPointerException error. download method failing on cordova / android platform with java.lang.NullPointerException exception Sep 14, 2023
@wilywork
Copy link

@the-other-sunny, Hello, did you find any solution?

@the-other-sunny
Copy link
Author

@the-other-sunny, Hello, did you find any solution?

the xhr approach ^^

@anubhavs19
Copy link

@the-other-sunny can you explain it a bit more, may be with some code. I am facing the same issue

@lchanouha
Copy link

lchanouha commented Mar 25, 2024

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

@the-other-sunny
Copy link
Author

@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.

@fuf-nf
Copy link

fuf-nf commented Apr 22, 2024

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 apache/cordova-plugin-file#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);
    });
  });
});

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants