package org.openintents.filemanager.util;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import org.openintents.filemanager.R;
import org.openintents.filemanager.files.FileHolder;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class CompressManager {
/**
* TAG for log messages.
*/
static final String TAG = "CompressManager";
private static final int BUFFER_SIZE = 1024;
private Context mContext;
private ProgressDialog progressDialog;
private int fileCount;
private String fileOut;
private OnCompressFinishedListener onCompressFinishedListener = null;
public CompressManager(Context context) {
mContext = context;
}
public void compress(FileHolder f, String out) {
List<FileHolder> list = new ArrayList<>(1);
list.add(f);
compress(list, out);
}
public void compress(List<FileHolder> list, String out) {
if (list.isEmpty()) {
Log.v(TAG, "couldn't compress empty file list");
return;
}
this.fileOut = list.get(0).getFile().getParent() + File.separator + out;
fileCount = 0;
for (FileHolder f : list) {
fileCount += FileUtils.getFileCount(f.getFile());
}
new CompressTask().execute(list);
}
public CompressManager setOnCompressFinishedListener(
OnCompressFinishedListener listener) {
this.onCompressFinishedListener = listener;
return this;
}
public interface OnCompressFinishedListener {
public abstract void compressFinished();
}
private class CompressTask extends
AsyncTask<List<FileHolder>, Void, Integer> {
private static final int SUCCESS = 0;
private static final int ERROR = 1;
private ZipOutputStream zos;
private File zipDirectory;
private boolean cancelCompression = false;
/**
* count of compressed file to update the progress bar
*/
private int isCompressed = 0;
/**
* Recursively compress file or directory
*
* @returns 0 if successful, error value otherwise.
*/
private void compressFile(File file, String path) throws IOException {
progressDialog.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface progressDialog) {
if (!cancelCompression) {
Log.e(TAG, "Dialog Dismissed");
Log.e(TAG, "Compression Cancel Attempted");
cancelCompression = true;
cancel(true);
}
}
});
if (!file.isDirectory()) {
byte[] buf = new byte[BUFFER_SIZE];
int len;
FileInputStream in = new FileInputStream(file);
if (path.length() > 0)
zos.putNextEntry(new ZipEntry(path + "/" + file.getName()));
else
zos.putNextEntry(new ZipEntry(file.getName()));
while ((len = in.read(buf)) > 0) {
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
return;
}
if (file.list() == null || cancelCompression) {
return;
}
for (String fileName : file.list()) {
if (cancelCompression) {
return;
}
File f = new File(file.getAbsolutePath() + File.separator
+ fileName);
compressFile(f, path + File.separator + file.getName());
isCompressed++;
progressDialog.setProgress((isCompressed * 100) / fileCount);
}
}
@Override
protected void onPreExecute() {
FileOutputStream out = null;
zipDirectory = new File(fileOut);
progressDialog = new ProgressDialog(mContext);
progressDialog.setCancelable(false);
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface progressDialog,
int which) {
progressDialog.dismiss();
Log.e(TAG, "Dialog Dismiss Detected");
}
});
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage(mContext.getString(R.string.compressing));
progressDialog.show();
progressDialog.setProgress(0);
try {
out = new FileOutputStream(zipDirectory);
zos = new ZipOutputStream(new BufferedOutputStream(out));
} catch (FileNotFoundException e) {
Log.e(TAG, "error while creating ZipOutputStream");
}
}
@Override
protected Integer doInBackground(List<FileHolder>... params) {
if (zos == null) {
return ERROR;
}
List<FileHolder> list = params[0];
for (FileHolder file : list) {
if (cancelCompression) {
return ERROR;
}
try {
compressFile(file.getFile(), "");
} catch (IOException e) {
Log.e(TAG, "Error while compressing", e);
return ERROR;
}
}
return SUCCESS;
}
@Override
protected void onCancelled(Integer result) {
Log.e(TAG, "onCancelled Initialised");
try {
zos.flush();
zos.close();
} catch (IOException e) {
Log.e(TAG, "error while closing zos", e);
}
if (zipDirectory.delete()) {
Log.e(TAG, "test deleted successfully");
} else {
Log.e(TAG, "error while deleting test");
}
Toast.makeText(mContext, "Compression Canceled", Toast.LENGTH_SHORT)
.show();
if (onCompressFinishedListener != null)
onCompressFinishedListener.compressFinished();
}
@Override
protected void onPostExecute(Integer result) {
try {
zos.flush();
zos.close();
} catch (IOException e) {
Log.e(TAG, "error while closing zos", e);
} catch (NullPointerException e) {
Log.e(TAG, "zos was null and couldn't be closed", e);
}
cancelCompression = true;
progressDialog.cancel();
if (result == ERROR) {
Toast.makeText(mContext, R.string.compressing_error,
Toast.LENGTH_SHORT).show();
} else if (result == SUCCESS) {
Toast.makeText(mContext, R.string.compressing_success,
Toast.LENGTH_SHORT).show();
}
if (onCompressFinishedListener != null)
onCompressFinishedListener.compressFinished();
}
}
}