Skip to content
New issue

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

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

Already on GitHub? Sign in 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);
    });
  });
});

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

No branches or pull requests

5 participants