Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output delayed from Cordova Plugin

I've written a Cordova plugin to download a file and save it in the data folder. Everything is working fine except for the return value. I would like to display a progress bar and need to get the current progress. Here's the relevant part from my code:

 while ((readed = is.read(buffer)) > 0) {
     fos.write(buffer, 0, readed);
     totalReaded += readed;

     int newProgress = (int) (totalReaded*100/fileSize);
     if (newProgress != progress) {
         progress = newProgress;
         PluginResult res = new PluginResult(PluginResult.Status.OK, progress);
         res.setKeepCallback(true);
         callbackContext.sendPluginResult(res);
     }
  }

My JavaScript:

downloader.prototype.writeFile = function (downloaderSuccess, downloaderFailure, options) {
    cordova.exec(downloaderSuccess, downloaderFailure, "downloader", "writeFile", options);
};

function downloaderSuccess(progress) {
    WL.Logger.debug("Result: "+progress)
}

function downloaderFailure(error) {
    WL.Logger.error("Error: "+error);
}

What happens is that the progress will only be output after the file has been downloaded. If I set the PluginResult.Status to NO_RESULT, it won't output anything at all.

like image 354
René Avatar asked Mar 19 '13 17:03

René


People also ask

Does Cordova use WebView?

Cordova applications are ordinarily implemented as a browser-based WebView within the native mobile platform.

How to debug Cordova iOS app?

To enable debugging on iOS, In the iOS device, go to Settings → Safari → Advanced → Enable 'Web Inspector' From the Mac, Safari → Preferences → Advanced → Enable 'Show Develop menu in menu bar' Once this is done, start the Cordova application and connect your iOS device with USB cable.

What are Cordova plugins?

A plugin is a package of injected code that allows the Cordova webview within which the app renders to communicate with the native platform on which it runs. Plugins provide access to device and platform functionality that is ordinarily unavailable to web-based apps.


1 Answers

are you using

   cordova.getThreadPool().execute(new Runnable() {
            public void run() {
                // while loop goes here
            }
        });

in the start of your download code?

Have a look at src/org/apache/cordova/FileTransfer.java. This files does pretty much what you are doing and you can see how they are able to send live progress updates because they are in a separate thread.

I think the problem is that both the JavaScript and the Java code run in the same WebCore thread so what is happening is that the download is blocking the communication between Java and the UI (eg, sending the result) until the download is done.

If you follow the advice in that guide about not blocking the WebCore thread (so, use: cordova.getThreadPool().execute()), you'll be able to get progress updates.

To test this, I took this plugin: https://github.com/phonegap/phonegap-plugins/blob/master/Android/Downloader/Downloader.java that does File downloading. As it stands, this code behaves the same as yours does - the progress update is sent only after the file is downloaded. However, once I wrapped the downloadUrl() method in the runnable, it worked fine, sending progress updates as they happened instead of waiting until the end.

Please let me know if this helps or if you'd like me to come up with a better explanation.

like image 108
MBillau Avatar answered Oct 18 '22 12:10

MBillau