diff --git a/.gitignore b/.gitignore index aa499374..6cc955d8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ /build.xml /target /lib/target +/cli/target diff --git a/cli/pom.xml b/cli/pom.xml new file mode 100644 index 00000000..898d3d53 --- /dev/null +++ b/cli/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + brut.apktool + apktool-cli + 1.3.3-SNAPSHOT + jar + + + brut.apktool + apktool-project + 1.0-SNAPSHOT + + + apktool cli + + + + brut.apktool + apktool-lib + 1.3.3-SNAPSHOT + + + diff --git a/cli/src/main/java/brut/apktool/Main.java b/cli/src/main/java/brut/apktool/Main.java new file mode 100644 index 00000000..f747a63a --- /dev/null +++ b/cli/src/main/java/brut/apktool/Main.java @@ -0,0 +1,275 @@ +/* + * Copyright 2010 Ryszard Wiśniewski . + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * under the License. + */ + +package brut.apktool; + +import brut.androlib.*; +import brut.androlib.err.CantFindFrameworkResException; +import brut.androlib.err.OutDirExistsException; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.logging.*; + +/** + * @author Ryszard Wiśniewski + */ +public class Main { + public static void main(String[] args) + throws IOException, AndrolibException, InterruptedException { + try { + boolean verbose = false; + int i; + for (i = 0; i < args.length; i++) { + String opt = args[i]; + if (! opt.startsWith("-")) { + break; + } + if ("-v".equals(opt) || "--verbose".equals(opt)) { + verbose = true; + } else { + throw new InvalidArgsError(); + } + } + setupLogging(verbose); + + if (args.length <= i) { + throw new InvalidArgsError(); + } + String cmd = args[i]; + args = Arrays.copyOfRange(args, i + 1, args.length); + + if ("d".equals(cmd) || "decode".equals(cmd)) { + cmdDecode(args); + } else if ("b".equals(cmd) || "build".equals(cmd)) { + cmdBuild(args); + } else if ("if".equals(cmd) || "install-framework".equals(cmd)) { + cmdInstallFramework(args); + } else if ("publicize-resources".equals(cmd)) { + cmdPublicizeResources(args); + } else { + throw new InvalidArgsError(); + } + } catch (InvalidArgsError ex) { + usage(); + System.exit(1); + } + } + + private static void cmdDecode(String[] args) throws InvalidArgsError, + AndrolibException { + ApkDecoder decoder = new ApkDecoder(); + + int i; + for (i = 0; i < args.length; i++) { + String opt = args[i]; + if (! opt.startsWith("-")) { + break; + } + if ("-s".equals(opt) || "--no-src".equals(opt)) { + decoder.setDecodeSources(ApkDecoder.DECODE_SOURCES_NONE); + } else if ("-d".equals(opt) || "--debug".equals(opt)) { + decoder.setDebugMode(true); + } else if ("-t".equals(opt) || "--frame-tag".equals(opt)) { + i++; + if (i >= args.length) { + throw new InvalidArgsError(); + } + decoder.setFrameworkTag(args[i]); + } else if ("-f".equals(opt) || "--force".equals(opt)) { + decoder.setForceDelete(true); + } else if ("-r".equals(opt) || "--no-res".equals(opt)) { + decoder.setDecodeResources(ApkDecoder.DECODE_RESOURCES_NONE); + } else if ("--keep-broken-res".equals(opt)) { + decoder.setKeepBrokenResources(true); + } else { + throw new InvalidArgsError(); + } + } + + String outName = null; + if (args.length == i + 2) { + outName = args[i + 1]; + } else if (args.length == i + 1) { + outName = args[i]; + outName = outName.endsWith(".apk") ? + outName.substring(0, outName.length() - 4) : outName + ".out"; + outName = new File(outName).getName(); + } else { + throw new InvalidArgsError(); + } + File outDir = new File(outName); + decoder.setOutDir(outDir); + decoder.setApkFile(new File(args[i])); + + try { + decoder.decode(); + } catch (OutDirExistsException ex) { + System.out.println( + "Destination directory (" + outDir.getAbsolutePath() + ") " + + "already exists. Use -f switch if you want to overwrite it."); + System.exit(1); + } catch (CantFindFrameworkResException ex) { + System.out.println( + "Can't find framework resources for package of id: " + + String.valueOf(ex.getPkgId()) + ". You must install proper " + + "framework files, see project website for more info."); + System.exit(1); + } + } + + private static void cmdBuild(String[] args) throws InvalidArgsError, + AndrolibException { + boolean forceBuildAll = false; + boolean debug = false; + int i; + for (i = 0; i < args.length; i++) { + String opt = args[i]; + if (! opt.startsWith("-")) { + break; + } + if ("-f".equals(opt) || "--force-all".equals(opt)) { + forceBuildAll = true; + } else if ("-d".equals(opt) || "--debug".equals(opt)) { + debug = true; + } else { + throw new InvalidArgsError(); + } + } + + String appDirName; + File outFile = null; + switch (args.length - i) { + case 0: + appDirName = "."; + break; + case 2: + outFile = new File(args[i + 1]); + case 1: + appDirName = args[i]; + break; + default: + throw new InvalidArgsError(); + } + + new Androlib().build(new File(appDirName), outFile, forceBuildAll, + debug); + } + + private static void cmdInstallFramework(String[] args) + throws AndrolibException { + String tag = null; + switch (args.length) { + case 2: + tag = args[1]; + case 1: + new Androlib().installFramework(new File(args[0]), tag); + return; + } + + throw new InvalidArgsError(); + } + + private static void cmdPublicizeResources(String[] args) + throws InvalidArgsError, AndrolibException { + if (args.length != 1) { + throw new InvalidArgsError(); + } + + new Androlib().publicizeResources(new File(args[0])); + } + + private static void usage() { + System.out.println( + "Apktool v" + Androlib.getVersion() + " - a tool for reengineering Android apk files\n" + + "Copyright 2010 Ryszard Wiśniewski \n" + + "Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n" + + "\n" + + "Usage: apktool [-v|--verbose] COMMAND [...]\n" + + "\n" + + "COMMANDs are:\n" + + "\n" + + " d[ecode] [OPTS] []\n" + + " Decode to .\n" + + "\n" + + " OPTS:\n" + + "\n" + + " -s, --no-src\n" + + " Do not decode sources.\n" + + " -r, --no-res\n" + + " Do not decode resources.\n" + + " -d, --debug\n" + + " Decode in debug mode. Check project page for more info.\n" + + " -f, --force\n" + + " Force delete destination directory.\n" + + " -t , --frame-tag \n" + + " Try to use framework files tagged by .\n" + + " --keep-broken-res\n" + + " Use if there was an error and some resources were dropped, e.g.:\n" + + " \"Invalid config flags detected. Dropping resources\", but you\n" + + " want to decode them anyway, even with errors. You will have to\n" + + " fix them manually before building." + + "\n" + + " b[uild] [OPTS] [] []\n" + + " Build an apk from already decoded application located in .\n" + + "\n" + + " It will automatically detect, whether files was changed and perform\n" + + " needed steps only.\n" + + "\n" + + " If you omit then current directory will be used.\n" + + " If you omit then /dist/\n" + + " will be used.\n" + + "\n" + + " OPTS:\n" + + "\n" + + " -f, --force-all\n" + + " Skip changes detection and build all files.\n" + + " -d, --debug\n" + + " Build in debug mode. Check project page for more info.\n" + + "\n" + + " if|install-framework []\n" + + " Install framework file to your system.\n" + + "\n" + + "For additional info, see: http://code.google.com/p/android-apktool/" + ); + } + + private static void setupLogging(boolean verbose) { + Logger logger = Logger.getLogger(""); + Handler handler = new ConsoleHandler(); + logger.removeHandler(logger.getHandlers()[0]); + logger.addHandler(handler); + + if (verbose) { + handler.setLevel(Level.ALL); + logger.setLevel(Level.ALL); + } else { + handler.setFormatter(new Formatter() { + @Override + public String format(LogRecord record) { + return record.getLevel().toString().charAt(0) + ": " + + record.getMessage() + + System.getProperty("line.separator"); + } + }); + } + } + + static class InvalidArgsError extends AndrolibException { + + } +} diff --git a/pom.xml b/pom.xml index a4ceb807..db805290 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,7 @@ lib + cli