Jeandre Pentz
Jeandre Pentz

Reputation: 1002

Phonegap cordova App gets paused Android

I have a phonegap application (Android). I make use of the plugin Downloader to download xml files. When I download a file my application "pauses" until the download is finished. I can't click on anything, my loaders don't work etc.

It use to work fine but I had to upgrade my app from cordova 1.8.0 to a new version (2.7.0).

I also altered the plugin itself to work with the new cordova.

I don't know what is causing this. Any ideas?.

-------EDIT: ADDED CODE---------

Here is my Downloader plugin class

public class Downloader extends CordovaPlugin {

public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {


    if (!action.equals("downloadFile")){
        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
        return true;
    }
    try {

        String fileUrl = args.getString(0);
        JSONObject params = args.getJSONObject(1);

        String fileName = params.has("fileName") ? 
                params.getString("fileName"):
                fileUrl.substring(fileUrl.lastIndexOf("/")+1);

        String dirName = params.has("dirName") ?
                params.getString("dirName"):
                    Environment.getExternalStorageDirectory().toString();

        Boolean overwrite = params.has("overwrite") ? params.getBoolean("overwrite") : false;

        callbackContext.sendPluginResult(this.downloadUrl(fileUrl, dirName, fileName, overwrite, callbackContext));
        return true;

    } catch (JSONException e) {

        e.printStackTrace();
        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage()));
        return false;

    } catch (InterruptedException e) {
        e.printStackTrace();
        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage()));
        return false;
    }

}
private PluginResult downloadUrl(String fileUrl, String dirName, String fileName, Boolean overwrite, CallbackContext callbackContext) throws InterruptedException, JSONException {


    try {

        Log.d("PhoneGapLog", "Downloading "+fileUrl + " into " + dirName + "/" + fileName);

        File dir = new File(dirName);
        if (!dir.exists()) {
            Log.d("PhoneGapLog", "directory " + dirName + " created");
            dir.mkdirs();
        }

        File file = new File(dirName, fileName);

        if (!overwrite && file.exists()) {
            Log.d("DownloaderPlugin", "File already exist");

            JSONObject obj = new JSONObject();
            obj.put("status", 1);
            obj.put("total", 0);
            obj.put("file", fileName);
            obj.put("dir", dirName);
            obj.put("progress", 100);

            return new PluginResult(PluginResult.Status.OK, obj);
        }

        URL url = new URL(fileUrl);
        HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
        ucon.setRequestMethod("GET");
        ucon.connect();

        Log.d("PhoneGapLog", "Download start");

        InputStream is = ucon.getInputStream();
        byte[] buffer = new byte[1024];
        int readed = 0, 
            progress = 0,
           // totalReaded = 0,
            fileSize = ucon.getContentLength();

        FileOutputStream fos = new FileOutputStream(file);

        while ((readed = is.read(buffer)) > 0) {

            fos.write(buffer, 0, readed);
            //totalReaded += readed;

            //int newProgress = (int) (totalReaded*100/fileSize);               
            //if (newProgress != progress)
            // progress = informProgress(fileSize, newProgress, dirName, fileName, callbackId);

        }

        fos.close();

        Log.d("PhoneGapLog", "Download finished");

        JSONObject obj = new JSONObject();
        obj.put("status", 1);
        obj.put("total", fileSize);
        obj.put("file", fileName);
        obj.put("dir", dirName);
        obj.put("progress", progress);

        return new PluginResult(PluginResult.Status.OK, obj);


    }
    catch (FileNotFoundException e) {
        Log.d("PhoneGapLog", "File Not Found: " + e);
        return new PluginResult(PluginResult.Status.ERROR, 404);
    }
    catch (IOException e) {
        Log.d("PhoneGapLog", "Error: " + e);
        return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
    }
}

}

Here is my Downloader plugin javascript

function Downloader() {}

Downloader.prototype.downloadFile = function(fileUrl, params, win, fail) {
//Make params hash optional.
if (!fail) win = params;
return cordova.exec(win, fail, "Downloader", "downloadFile", [fileUrl, params]);
};

 if(!window.plugins) {
    window.plugins = {};
 }
 if (!window.plugins.downloader) {
   window.plugins.downloader = new Downloader();
 }

And when I call it

$.mobile.showPageLoadingMsg();
window.plugins.downloader.downloadFile("URL",
                        {overwrite: true,
                        dirName: dir, fileName: "File.xml"}, 
                      function() {
                            alert("finished");      
                    }, function(error) {
                        alert("fail");
                );

The loader that apears because of showPageLoadingMsg will either freeze until the download is finish or only show up once the download is finished

Upvotes: 0

Views: 868

Answers (1)

Mixaz
Mixaz

Reputation: 4178

PhoneGap plugin methods are called on UI thread of whole application, you should not perform long activities in UI thread, otherwise it gets blocked, no UI updates and even whole app becomes unresponsible. Please read docs - you should perform long tasks in separate thread, releasing the UI thread to PhoneGap. It is made in 2 steps - you start a new thread and return

PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
r.setKeepCallback(true);
callContext.sendPluginResult(r);

with a flag that it will be a async plugin call. When the thread finishes, you finish the call with

callContext.success(json);

EDIT:

I was wrong that Cordova Plugin methods are called on UI thread, they are called on WebCore thread which is not the same as the UI one (and it is important to remember if you need to show some UI in plugin). Anyway you should not block the WebCore thread as well, see documentation:

Threading

JavaScript in the WebView does not run on the UI thread. It runs on the WebCore thread. The execute method also runs on the WebCore thread.

http://docs.phonegap.com/en/2.2.0/guide_plugin-development_android_index.md.html

Upvotes: 1

Related Questions