Skip to content

Commit

Permalink
Add progress feedback while unzipping (Android).
Browse files Browse the repository at this point in the history
  • Loading branch information
adangel authored and mmocny committed Mar 27, 2014
1 parent 2843157 commit 8c58008
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 7 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,22 @@ A Cordova plugin to unzip files in Android and iOS.

##Usage

zip.unzip(<source zip>, <destination dir>, <callback>);
zip.unzip(<source zip>, <destination dir>, <callback>, [<progressCallback>]);

Both source and destination arguments can be URLs obtained from the HTML File
interface or absolute paths to files on the device.

The callback argument will be executed when the unzip is complete, or when an
error occurs. It will be called with a single argument, which will be 0 on
success, or -1 on failure.

The progressCallback argument is optional and will be executed whenever a new ZipEntry
has been extracted. E.g.:

var progressCallback = function(progressEvent) {
$( "#progressbar" ).progressbar("value", Math.round((progressEvent.loaded / progressEvent.total) * 100));
};

The values `loaded` and `total` are the number of compressed bytes processed and total. Total is the
file size of the zip file.

51 changes: 50 additions & 1 deletion src/android/Zip.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
import android.net.Uri;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi.OpenForReadResult;
import org.apache.cordova.PluginResult;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

Expand Down Expand Up @@ -64,7 +67,11 @@ private void unzipSync(CordovaArgs args, CallbackContext callbackContext) {
throw new FileNotFoundException("File: \"" + outputDirectory + "\" not found");
}

InputStream is = resourceApi.openForRead(zipUri).inputStream;
OpenForReadResult zipFile = resourceApi.openForRead(zipUri);
ProgressEvent progress = new ProgressEvent();
progress.setTotal(zipFile.length);

InputStream is = zipFile.inputStream;

if (zipFileName.endsWith("crx")) {
// CRX files contain a header. This header consists of:
Expand All @@ -86,6 +93,8 @@ private void unzipSync(CordovaArgs args, CallbackContext callbackContext) {
is.skip(2);

is.skip(pubkeyLength + signatureLength);

progress.setLoaded(4 + 4 + 4 + 4 + pubkeyLength + signatureLength);
}

// The inputstream is now pointing at the start of the actual zip file content.
Expand All @@ -96,6 +105,8 @@ private void unzipSync(CordovaArgs args, CallbackContext callbackContext) {
byte[] buffer = new byte[1024];
boolean anyEntries = false;

updateProgress(callbackContext, progress);

while ((ze = zis.getNextEntry()) != null)
{
anyEntries = true;
Expand All @@ -118,9 +129,16 @@ private void unzipSync(CordovaArgs args, CallbackContext callbackContext) {
}

}
progress.addLoaded(ze.getCompressedSize());
updateProgress(callbackContext, progress);
zis.closeEntry();
}
zis.close();

// final progress = 100%
progress.setLoaded(progress.getTotal());
updateProgress(callbackContext, progress);

if (anyEntries)
callbackContext.success();
else
Expand All @@ -132,10 +150,41 @@ private void unzipSync(CordovaArgs args, CallbackContext callbackContext) {
}
}

private void updateProgress(CallbackContext callbackContext, ProgressEvent progress) throws JSONException {
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
pluginResult.setKeepCallback(true);
callbackContext.sendPluginResult(pluginResult);
}

private Uri getUriForArg(String arg) {
CordovaResourceApi resourceApi = webView.getResourceApi();
Uri tmpTarget = Uri.parse(arg);
return resourceApi.remapUri(
tmpTarget.getScheme() != null ? tmpTarget : Uri.fromFile(new File(arg)));
}

private static class ProgressEvent {
private long loaded;
private long total;
public long getLoaded() {
return loaded;
}
public void setLoaded(long loaded) {
this.loaded = loaded;
}
public void addLoaded(long add) {
this.loaded += add;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public JSONObject toJSONObject() throws JSONException {
return new JSONObject(
"{loaded:" + loaded +
",total:" + total + "}");
}
}
}
26 changes: 21 additions & 5 deletions zip.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
var exec = cordova.require('cordova/exec');

exports.unzip = function(fileName, outputDirectory, callback) {
var win = callback && function() {
callback(0);
function newProgressEvent(result) {
var event = {
loaded: result.loaded,
total: result.total
};
var fail = callback && function() {
callback(-1);
return event;
}

exports.unzip = function(fileName, outputDirectory, callback, progressCallback) {
var win = function(result) {
if (result && typeof result.loaded != "undefined") {
if (progressCallback) {
return progressCallback(newProgressEvent(result));
}
} else if (callback) {
callback(0);
}
};
var fail = function(result) {
if (callback) {
callback(-1);
}
};
exec(win, fail, 'Zip', 'unzip', [fileName, outputDirectory]);
};

0 comments on commit 8c58008

Please sign in to comment.