这是基于@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 boolean deleteDirectory(String file) {
try {
if (new File(file).exists()) {
String deleteCommand = "rm -rf " + file;
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();
}
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 total = 0;
ZipInputStream zin = new ZipInputStream(stream);
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();
if (ze.isDirectory()) {
dirChecker(destination, ze.getName());
} else {
File f = new File(destination, ze.getName());
if (!f.exists()) {
boolean success = f.createNewFile();
if (!success) {
continue;
}
FileOutputStream fout = new FileOutputStream(f);
int count;
while ((count = zin.read(buffer)) != -1) {
fout.write(buffer, 0, count);
totalBytes += count;
}
zin.closeEntry();
fout.close();
}
}
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() {
}
});
}
@Override
public void finish() {
((UpdateActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
@Override
public void error(String error) {
((UpdateActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
});
zipUtility.unzipFromPath(context,
zipFilePath,
context.getFilesDir().getAbsolutePath() + File.separator);
}
}).start();
}