public static void unzip(final String file, final UnzipListener callback)
			throws IOException, InterruptedException {
		final byte[] buffer = new byte[BUFFER_SIZE];
		final File f = new File(file);
		final File d = f.getParentFile();
		if (!d.exists()) {
			d.mkdir();
		}
		// Total number of entries.
		final ZipFile zf = new ZipFile(f);
		final double progress = 100 / (double) zf.size();
		zf.close();
		// Extract.
		try (ZipInputStream zis = new ZipInputStream(new FileInputStream(f))) {
			ZipEntry ze = null;
			int i = 0;
			while ((ze = zis.getNextEntry()) != null) {
				// Check for interrupt.
				if (Thread.currentThread().isInterrupted()) {
					throw new InterruptedException();
				}
				// Create the file.
				final String fileName = ze.getName();
				final File newFile = new File(d, fileName);
				new File(newFile.getParent()).mkdirs();
				try (FileOutputStream fos = new FileOutputStream(newFile)) {
					int len;
					while ((len = zis.read(buffer)) > 0) {
						// Check for interrupt.
						if (Thread.currentThread().isInterrupted()) {
							throw new InterruptedException();
						}
						// Read the bytes.
						fos.write(buffer, 0, len);
					}
				}
				if (callback != null) {
					++i;
					callback.onProgress(i * progress);
				}
			}
		}
	}