diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index e10ed96147..8f534220ce 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -270,6 +270,19 @@ private static void cmdBuild(CommandLine cli, Config config) { if (cli.hasOption("use-aapt1")) { config.useAapt2 = false; } + if (cli.hasOption("l") ||cli.hasOption("compression-level")) { + try { + int intValue = Integer.parseInt(cli.getOptionValue("l")); + if (intValue < -1 || intValue > 9) { + System.err.println("Compression level must be a value between 0 and 9 or -1 for default."); + System.exit(1); + } + config.zipCompressionLevel = intValue; + } catch (NumberFormatException e) { + System.err.println("Compression level isn't a number."); + System.exit(1); + } + } if (cli.hasOption("use-aapt1") && cli.hasOption("use-aapt2")) { System.err.println("You can only use one of --use-aapt1 or --use-aapt2."); @@ -471,6 +484,13 @@ private static void _options() { .desc("Disable crunching of resource files during the build step.") .build(); + Option compressionLevelOption = Option.builder("l") + .longOpt("compression-level") + .desc("Zip file compression level (A number between 0 and 9 or -1 for default)") + .hasArg(true) + .argName("level") + .build(); + Option tagOption = Option.builder("t") .longOpt("tag") .desc("Tag frameworks using .") @@ -579,6 +599,7 @@ private static void _options() { allOptions.addOption(aapt2Option); allOptions.addOption(noCrunchOption); allOptions.addOption(onlyMainClassesOption); + allOptions.addOption(compressionLevelOption); } private static String verbosityHelp() { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java index 39eecdb66b..61bacbec5a 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkBuilder.java @@ -442,6 +442,7 @@ private void buildUnknownFiles(File outFile) throws AndrolibException { ZipFile inputFile = new ZipFile(tempFile); ZipOutputStream actualOutput = new ZipOutputStream(Files.newOutputStream(outFile.toPath())) ) { + actualOutput.setLevel(mConfig.zipCompressionLevel); copyExistingFiles(inputFile, actualOutput); copyUnknownFiles(actualOutput, files); } catch (IOException | BrutException ex) { @@ -534,7 +535,7 @@ private void buildApk(File outApk) throws AndrolibException { private void zipPackage(File apkFile, File rawDir, File assetDir) throws AndrolibException { try { - ZipUtils.zipFolders(rawDir, apkFile, assetDir, mApkInfo.doNotCompress); + ZipUtils.zipFolders(rawDir, apkFile, assetDir, mApkInfo.doNotCompress, mConfig.zipCompressionLevel); } catch (IOException | BrutException ex) { throw new AndrolibException(ex); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java index 5ac8b020e1..0aad29e800 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Config.java @@ -21,6 +21,7 @@ import java.io.File; import java.util.logging.Logger; +import java.util.zip.Deflater; public class Config { private static Config instance = null; @@ -53,6 +54,7 @@ public class Config { public boolean updateFiles = false; public boolean useAapt2 = true; public boolean noCrunch = false; + public int zipCompressionLevel = Deflater.DEFAULT_COMPRESSION; // Decode options public short decodeSources = DECODE_SOURCES_SMALI; diff --git a/brut.j.dir/src/main/java/brut/directory/ZipUtils.java b/brut.j.dir/src/main/java/brut/directory/ZipUtils.java index 3e71990016..49c01cd763 100644 --- a/brut.j.dir/src/main/java/brut/directory/ZipUtils.java +++ b/brut.j.dir/src/main/java/brut/directory/ZipUtils.java @@ -25,6 +25,7 @@ import java.nio.file.Files; import java.util.Collection; import java.util.zip.CRC32; +import java.util.zip.Deflater; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -36,11 +37,12 @@ private ZipUtils() { // Private constructor for utility class } - public static void zipFolders(final File folder, final File zip, final File assets, final Collection doNotCompress) + public static void zipFolders(final File folder, final File zip, final File assets, final Collection doNotCompress, final int level) throws BrutException, IOException { mDoNotCompress = doNotCompress; ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zip.toPath())); + zipOutputStream.setLevel(level); zipFolders(folder, zipOutputStream); // We manually set the assets because we need to retain the folder structure