这是我基于@davorb 想法的解决方案,它根据文件大小而不是 zip 文件的内容显示进度。
import android.content.Context;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipUtility {
private final String TAG = "Decompress";
private ZipExtractionCallback zipExtractionCallback;
public ZipUtility(ZipExtractionCallback zipExtractionCallback) {
this.zipExtractionCallback = zipExtractionCallback;
}
//
// private void unzipFromAssets(Context context, String zipFile, String destination) {
// try {
// if (destination == null || destination.length() == 0)
// destination = context.getFilesDir().getAbsolutePath();
// new File(destination).delete();
// InputStream stream = context.getAssets().open(zipFile);
// unzip(stream, destination);
//// SharedPreferenceHelper.Write(context,
//// SharedPreferenceConst.SharedPreferenceName,
//// SharedPreferenceConst.MapExtracted,
//// "1");
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
private boolean deleteDirectory(String file) /*throws IOException, InterruptedException */ {
try {
if (new File(file).exists()) {
String deleteCommand = "rm -rf " + file/*.getAbsolutePath()*/;
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(deleteCommand);
process.waitFor();
return true;
}
} catch (Exception ignore) {
}
return false;
}
public void unzipFromPath(Context context, String zipFilePath, String destination) {
try {
if (destination == null || destination.length() == 0)
destination = context.getFilesDir().getAbsolutePath();
zipExtractionCallback.progress(0, "حذف فایل های قدیمی...");
deleteDirectory(destination + "html");
unzip(zipFilePath, destination);
zipExtractionCallback.progress(0, "حذف فایل اضافی...");
deleteDirectory(zipFilePath);
} catch (IOException e) {
zipExtractionCallback.error("خطا هنگام عملیات استخراج : " + e.getMessage());
e.printStackTrace();
}
zipExtractionCallback.finish();
}
//
// public static void unzip(String zipFile, String location) {
// try {
// FileInputStream fin = new FileInputStream(zipFile);
// unzip(fin, location);
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
//
// }
private void unzip(String zipFilePath, String destination) throws IOException {
long size = new File(zipFilePath).length();
long decompressedSize = 0;
InputStream stream = new FileInputStream(new File(zipFilePath));
dirChecker(destination, "");
// int entries = 0;
int total = 0;
ZipInputStream zin = new ZipInputStream(stream);
// while ((zin.getNextEntry()) != null) {
// if (entries % 100 == 0)
// zipExtractionCallback.progress(0, "در حال خواندن محتویات:" + entries + " فایل");
// entries++;
// }
zin.close();
stream = new FileInputStream(new File(zipFilePath));
int p = 0;
long totalBytes = 0;
int BUFFER_SIZE = 1024 * 10;
byte[] buffer = new byte[BUFFER_SIZE];
try {
zin = new ZipInputStream(stream);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
decompressedSize += ze.getSize();
//Log.v(TAG, "Unzipping " + ze.getName());
if (ze.isDirectory()) {
dirChecker(destination, ze.getName());
} else {
File f = new File(destination, ze.getName());
if (!f.exists()) {
boolean success = f.createNewFile();
if (!success) {
//Log.w(TAG, "Failed to create file " + f.getName());
continue;
}
FileOutputStream fout = new FileOutputStream(f);
//BufferedOutputStream out = new BufferedOutputStream(fout);
int count;
while ((count = zin.read(buffer)) != -1) {
fout.write(buffer, 0, count);
//out.write(buffer, 0, count);
totalBytes += count;
}
zin.closeEntry();
fout.close();
}
}
// int progress = 1 + (total++ * 100 / entries);
if (size < decompressedSize)
size = decompressedSize;
int progress = (int) ( (totalBytes * 100L / size));
if (p < progress)
zipExtractionCallback.progress(progress, "در حال استخراج از حالت فشرده:");
p = progress;
}
zin.close();
} catch (Exception e) {
zipExtractionCallback.error("خطا هنگام عملیات استخراج : " + e.getMessage());
Log.e(TAG, "unzip", e);
}
}
private void dirChecker(String destination, String dir) {
File f = new File(destination, dir);
if (!f.isDirectory()) {
boolean success = f.mkdirs();
if (!success) {
Log.w(TAG, "Failed to create folder " + f.getName());
}
}
}
public interface ZipExtractionCallback {
void progress(int progress, String status);
void finish();
void error(String error);
}
}
使用它的例子:
private void ExtractMap(String zipFilePath,Context context) {
new Thread(new Runnable() {
@Override
public void run() {
ZipUtility zipUtility = new ZipUtility(new ZipUtility.ZipExtractionCallback() {
@Override
public void progress(int progress, String status) {
((UpdateActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
//todo handle ui
}
});
}
@Override
public void finish() {
((UpdateActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
//todo handle ui
}
});
}
@Override
public void error(String error) {
((UpdateActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
//todo handle ui
}
});
}
});
zipUtility.unzipFromPath(context,
zipFilePath,
context.getFilesDir().getAbsolutePath() + File.separator);
}
}).start();
}