Android之zip文件加密解压及进度条的实现

zip文件的解压能够使用java的zip库,可是没有实现对加密文件的解压功能,这里能够使用zip4j来实现。详细能够參看该文《Android下zip压缩文件加密解密的完美解决方式》。该文件里没有实现解压进度的功能,这里进行一简单的实现。

Zip4jSp.java

/**
	 * unzip file to dest dir with password in thread.
	 * 
	 * @param zipFile
	 * @param dest
	 * @param passwd
	 * @param charset
	 *            null or empty is utf-8
	 * @param Handler
	 *            handler in thread
	 * @param isDeleteZipFile
	 *            true:delete zip file.false:not.
	 * @throws ZipException
	 */
	public static void Unzip(final File zipFile, String dest, String passwd,
			String charset, final Handler handler, final boolean isDeleteZipFile)
			throws ZipException {
		ZipFile zFile = new ZipFile(zipFile);
		if (TextUtils.isEmpty(charset)) {
			charset = "UTF-8";
		}
		zFile.setFileNameCharset(charset);
		if (!zFile.isValidZipFile()) {
			throw new ZipException(
					"Compressed files are not illegal, may be damaged.");
		}
		File destDir = new File(dest); // Unzip directory
		if (destDir.isDirectory() && !destDir.exists()) {
			destDir.mkdir();
		}
		if (zFile.isEncrypted()) {
			zFile.setPassword(passwd.toCharArray());
		}

		final ProgressMonitor progressMonitor = zFile.getProgressMonitor();

		Thread progressThread = new Thread(new Runnable() {

			@Override
			public void run() {
				Bundle bundle = null;
				Message msg = null;
				try {
					int percentDone = 0;
					// long workCompleted=0;
					// handler.sendEmptyMessage(ProgressMonitor.RESULT_SUCCESS)
					if (handler == null) {
						return;
					}
					handler.sendEmptyMessage(CompressStatus.START);
					while (true) {
						Thread.sleep(1000);

						percentDone = progressMonitor.getPercentDone();						
						bundle = new Bundle();
						bundle.putInt(CompressKeys.PERCENT, percentDone);
						msg = new Message();
						msg.what = CompressStatus.HANDLING;
						msg.setData(bundle);
						handler.sendMessage(msg);
						if (percentDone >= 100) {
							break;
						}
					}
					handler.sendEmptyMessage(CompressStatus.COMPLETED);					
				} catch (InterruptedException e) {
					bundle = new Bundle();
					bundle.putString(CompressKeys.ERROR, e.getMessage());
					msg = new Message();
					msg.what = CompressStatus.ERROR;
					msg.setData(bundle);
					handler.sendMessage(msg);
					e.printStackTrace();
				}
				finally
				{
					if(isDeleteZipFile)
					{
						zipFile.deleteOnExit();//zipFile.delete();
					}
				}
			}
		});

		progressThread.start();
		zFile.setRunInThread(true);
		zFile.extractAll(dest);
	}

注:

(1)、字符集默认採用UTF-8

(2)、解压文件在线程中进行,所以须要setRunInThread(true).因为採用线程中解压文件,所以调用该函数时相当于异步运行,调用代码会直接往下走,须要注意并加以处理。

(3)、进度条另开了一个线程来处理,并将处理的结果以handler的形式发送

(4)、使用zipFile.deleteOnExit()而不是zipFile.delete();由于使用线程解压时,尽管从progressMonitor获得的percentDone已经达到了100,而其实数据并没有全然解压完毕。这时退出循环执行finally的delete函数,假设使用zipFile.delete(),将会删除文件,这样会使兴许的解压失败。而使用zipFile.deleteOnExit()函数,该函数是当VM终止时才会删除文件,与zipFile.delete()删除文件不同。APP在执行时,VM始终是在的,所以这样删除可以确保兴许的解压可以正常进行。或者不去删除文件。

(5)、handler的代码见后文的MainActivity.java。


CompressKeys.java
package com.sparkle.compress;

public class CompressKeys {
	public final static String PERCENT="PERCENT";
	public final static String ERROR="ERROR";
}


CompressStatus.java

package com.sparkle.compress;

public class CompressStatus {
	public final static int START=0;
	public final static int HANDLING=1;
	public final static int COMPLETED=2;
	public final static int ERROR=3;
}


MainActivity.java
	private Handler _handler=new Handler(){
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case CompressStatus.START:
			{
				setTitle("Start...");
				break;
			}
			case CompressStatus.HANDLING:
			{
				Bundle bundle=msg.getData();
				int percent=bundle.getInt(CompressKeys.PERCENT);
				setTitle(percent+"%");
				break;
			}
			case CompressStatus.ERROR:
			{
				Bundle bundle=msg.getData();
				String error=bundle.getString(CompressKeys.ERROR);
				_info_textView.setText(error);
				break;
			}
			case CompressStatus.COMPLETED:
			{
				setTitle("Completed");
				byte[] data=FileSp.read(tempFilePath);
				try {
					String dataStr=new String(data,"UTF-8");
					_info_textView.setText(dataStr);
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}				
				break;
			}
			default:
				break;
			}			
			
		};
	};
}

以下是效果图

Android之zip文件加密解压及进度条的实现