2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.sdklib.build;
21 import java.io.FilenameFilter;
22 import java.util.ArrayList;
23 import java.util.regex.Pattern;
27 * Command line APK builder with signing support.
29 public final class ApkBuilderMain {
31 private final static Pattern PATTERN_JAR_EXT = Pattern.compile("^.+\\.jar$",
32 Pattern.CASE_INSENSITIVE);
35 * Main method. This is meant to be called from the command line through an exec.
36 * <p/>WARNING: this will call {@link System#exit(int)} if anything goes wrong.
37 * @param args command line arguments.
39 public static void main(String[] args) {
40 if (args.length < 1) {
44 System.err.println("\nTHIS TOOL IS DEPRECATED. See --help for more information.\n");
47 File outApk = new File(args[0]);
50 ArrayList<File> zipArchives = new ArrayList<File>();
51 ArrayList<File> sourceFolders = new ArrayList<File>();
52 ArrayList<File> jarFiles = new ArrayList<File>();
53 ArrayList<File> nativeFolders = new ArrayList<File>();
55 boolean verbose = false;
56 boolean signed = true;
57 boolean debug = false;
61 String argument = args[index++];
63 if ("-v".equals(argument)) {
66 } else if ("-d".equals(argument)) {
69 } else if ("-u".equals(argument)) {
72 } else if ("-z".equals(argument)) {
73 // quick check on the next argument.
74 if (index == args.length) {
75 printAndExit("Missing value for -z");
78 zipArchives.add(new File(args[index++]));
79 } else if ("-f". equals(argument)) {
80 if (dexFile != null) {
81 // can't have more than one dex file.
82 printAndExit("Can't have more than one dex file (-f)");
84 // quick check on the next argument.
85 if (index == args.length) {
86 printAndExit("Missing value for -f");
89 dexFile = new File(args[index++]);
90 } else if ("-rf". equals(argument)) {
91 // quick check on the next argument.
92 if (index == args.length) {
93 printAndExit("Missing value for -rf");
96 sourceFolders.add(new File(args[index++]));
97 } else if ("-rj". equals(argument)) {
98 // quick check on the next argument.
99 if (index == args.length) {
100 printAndExit("Missing value for -rj");
103 jarFiles.add(new File(args[index++]));
104 } else if ("-nf".equals(argument)) {
105 // quick check on the next argument.
106 if (index == args.length) {
107 printAndExit("Missing value for -nf");
110 nativeFolders.add(new File(args[index++]));
111 } else if ("-storetype".equals(argument)) {
112 // quick check on the next argument.
113 if (index == args.length) {
114 printAndExit("Missing value for -storetype");
119 printAndExit("Unknown argument: " + argument);
121 } while (index < args.length);
123 if (zipArchives.size() == 0) {
124 printAndExit("No zip archive, there must be one for the resources");
127 // create the builder with the basic files.
128 ApkBuilder builder = new ApkBuilder(outApk, zipArchives.get(0), dexFile,
129 signed ? ApkBuilder.getDebugKeystore() : null,
130 verbose ? System.out : null);
131 builder.setDebugMode(debug);
133 // add the rest of the files.
134 // first zip Archive was used in the constructor.
135 for (int i = 1 ; i < zipArchives.size() ; i++) {
136 builder.addZipFile(zipArchives.get(i));
139 for (File sourceFolder : sourceFolders) {
140 builder.addSourceFolder(sourceFolder);
143 for (File jarFile : jarFiles) {
144 if (jarFile.isDirectory()) {
145 String[] filenames = jarFile.list(new FilenameFilter() {
146 public boolean accept(File dir, String name) {
147 return PATTERN_JAR_EXT.matcher(name).matches();
151 for (String filename : filenames) {
152 builder.addResourcesFromJar(new File(jarFile, filename));
155 builder.addResourcesFromJar(jarFile);
159 for (File nativeFolder : nativeFolders) {
160 builder.addNativeLibraries(nativeFolder, null /*abiFilter*/);
167 } catch (ApkCreationException e) {
168 printAndExit(e.getMessage());
169 } catch (DuplicateFileException e) {
170 printAndExit(String.format(
171 "Found duplicate file for APK: %1$s\nOrigin 1: %2$s\nOrigin 2: %3$s",
172 e.getArchivePath(), e.getFile1(), e.getFile2()));
173 } catch (SealedApkException e) {
174 printAndExit(e.getMessage());
175 } catch (Exception e) {
180 private static void printUsageAndQuit() {
181 // 80 cols marker: 01234567890123456789012345678901234567890123456789012345678901234567890123456789
182 System.err.println("\n\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
183 System.err.println("THIS TOOL IS DEPRECATED and may stop working at any time!\n");
184 System.err.println("If you wish to use apkbuilder for a custom build system, please look at the");
185 System.err.println("com.android.sdklib.build.ApkBuilder which provides support for");
186 System.err.println("recent build improvements including library projects.");
187 System.err.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n");
188 System.err.println("A command line tool to package an Android application from various sources.");
189 System.err.println("Usage: apkbuilder <out archive> [-v][-u][-storetype STORE_TYPE] [-z inputzip]");
190 System.err.println(" [-f inputfile] [-rf input-folder] [-rj -input-path]");
191 System.err.println("");
192 System.err.println(" -v Verbose.");
193 System.err.println(" -d Debug Mode: Includes debug files in the APK file.");
194 System.err.println(" -u Creates an unsigned package.");
195 System.err.println(" -storetype Forces the KeyStore type. If ommited the default is used.");
196 System.err.println("");
197 System.err.println(" -z Followed by the path to a zip archive.");
198 System.err.println(" Adds the content of the application package.");
199 System.err.println("");
200 System.err.println(" -f Followed by the path to a file.");
201 System.err.println(" Adds the file to the application package.");
202 System.err.println("");
203 System.err.println(" -rf Followed by the path to a source folder.");
204 System.err.println(" Adds the java resources found in that folder to the application");
205 System.err.println(" package, while keeping their path relative to the source folder.");
206 System.err.println("");
207 System.err.println(" -rj Followed by the path to a jar file or a folder containing");
208 System.err.println(" jar files.");
209 System.err.println(" Adds the java resources found in the jar file(s) to the application");
210 System.err.println(" package.");
211 System.err.println("");
212 System.err.println(" -nf Followed by the root folder containing native libraries to");
213 System.err.println(" include in the application package.");
218 private static void printAndExit(String... messages) {
219 for (String message : messages) {
220 System.err.println(message);
225 private ApkBuilderMain() {