Main.cpp revision 62da8461ed5317fe78ae5e3793662694e7fc99a3
1// 2// Copyright 2006 The Android Open Source Project 3// 4// Android Asset Packaging Tool main entry point. 5// 6#include "Main.h" 7#include "Bundle.h" 8 9#include <utils.h> 10#include <utils/ZipFile.h> 11 12#include <stdlib.h> 13#include <getopt.h> 14#include <assert.h> 15 16using namespace android; 17 18static const char* gProgName = "aapt"; 19 20/* 21 * When running under Cygwin on Windows, this will convert slash-based 22 * paths into back-slash-based ones. Otherwise the ApptAssets file comparisons 23 * fail later as they use back-slash separators under Windows. 24 * 25 * This operates in-place on the path string. 26 */ 27void convertPath(char *path) { 28 if (path != NULL && OS_PATH_SEPARATOR != '/') { 29 for (; *path; path++) { 30 if (*path == '/') { 31 *path = OS_PATH_SEPARATOR; 32 } 33 } 34 } 35} 36 37/* 38 * Print usage info. 39 */ 40void usage(void) 41{ 42 fprintf(stderr, "Android Asset Packaging Tool\n\n"); 43 fprintf(stderr, "Usage:\n"); 44 fprintf(stderr, 45 " %s l[ist] [-v] [-a] file.{zip,jar,apk}\n" 46 " List contents of Zip-compatible archive.\n\n", gProgName); 47 fprintf(stderr, 48 " %s d[ump] WHAT file.{apk} [asset [asset ...]]\n" 49 " badging Print the label and icon for the app declared in APK.\n" 50 " permissions Print the permissions from the APK.\n" 51 " resources Print the resource table from the APK.\n" 52 " configurations Print the configurations in the APK.\n" 53 " xmltree Print the compiled xmls in the given assets.\n" 54 " xmlstrings Print the strings of the given compiled xml assets.\n\n", gProgName); 55 fprintf(stderr, 56 " %s p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \\\n" 57 " [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \\\n" 58 " [--min-sdk-version VAL] [--target-sdk-version VAL] \\\n" 59 " [--max-sdk-version VAL] [--app-version VAL] \\\n" 60 " [--app-version-name TEXT] \\\n" 61 " [-I base-package [-I base-package ...]] \\\n" 62 " [-A asset-source-dir] [-P public-definitions-file] \\\n" 63 " [-S resource-sources [-S resource-sources ...]] " 64 " [-F apk-file] [-J R-file-dir] \\\n" 65 " [raw-files-dir [raw-files-dir] ...]\n" 66 "\n" 67 " Package the android resources. It will read assets and resources that are\n" 68 " supplied with the -M -A -S or raw-files-dir arguments. The -J -P -F and -R\n" 69 " options control which files are output.\n\n" 70 , gProgName); 71 fprintf(stderr, 72 " %s r[emove] [-v] file.{zip,jar,apk} file1 [file2 ...]\n" 73 " Delete specified files from Zip-compatible archive.\n\n", 74 gProgName); 75 fprintf(stderr, 76 " %s a[dd] [-v] file.{zip,jar,apk} file1 [file2 ...]\n" 77 " Add specified files to Zip-compatible archive.\n\n", gProgName); 78 fprintf(stderr, 79 " %s v[ersion]\n" 80 " Print program version.\n\n", gProgName); 81 fprintf(stderr, 82 " Modifiers:\n" 83 " -a print Android-specific data (resources, manifest) when listing\n" 84 " -c specify which configurations to include. The default is all\n" 85 " configurations. The value of the parameter should be a comma\n" 86 " separated list of configuration values. Locales should be specified\n" 87 " as either a language or language-region pair. Some examples:\n" 88 " en\n" 89 " port,en\n" 90 " port,land,en_US\n" 91 " If you put the special locale, zz_ZZ on the list, it will perform\n" 92 " pseudolocalization on the default locale, modifying all of the\n" 93 " strings so you can look for strings that missed the\n" 94 " internationalization process. For example:\n" 95 " port,land,zz_ZZ\n" 96 " -d one or more device assets to include, separated by commas\n" 97 " -f force overwrite of existing files\n" 98 " -g specify a pixel tolerance to force images to grayscale, default 0\n" 99 " -j specify a jar or zip file containing classes to include\n" 100 " -m make package directories under location specified by -J\n" 101#if 0 102 " -p pseudolocalize the default configuration\n" 103#endif 104 " -u update existing packages (add new, replace older, remove deleted files)\n" 105 " -v verbose output\n" 106 " -x create extending (non-application) resource IDs\n" 107 " -z require localization of resource attributes marked with\n" 108 " localization=\"suggested\"\n" 109 " -A additional directory in which to find raw asset files\n" 110 " -F specify the apk file to output\n" 111 " -I add an existing package to base include set\n" 112 " -J specify where to output R.java resource constant definitions\n" 113 " -M specify full path to AndroidManifest.xml to include in zip\n" 114 " -P specify where to output public resource definitions\n" 115 " -S directory in which to find resources. Multiple directories will be scanned" 116 " and the first match found (left to right) will take precedence." 117 " -0 specifies an additional extension for which such files will not\n" 118 " be stored compressed in the .apk. An empty string means to not\n" 119 " compress any files at all.\n" 120 " --min-sdk-version\n" 121 " inserts android:minSdkVersion in to manifest.\n" 122 " --target-sdk-version\n" 123 " inserts android:targetSdkVersion in to manifest.\n" 124 " --max-sdk-version\n" 125 " inserts android:maxSdkVersion in to manifest.\n" 126 " --version-code\n" 127 " inserts android:versionCode in to manifest.\n" 128 " --version-name\n" 129 " inserts android:versionName in to manifest.\n"); 130} 131 132/* 133 * Dispatch the command. 134 */ 135int handleCommand(Bundle* bundle) 136{ 137 //printf("--- command %d (verbose=%d force=%d):\n", 138 // bundle->getCommand(), bundle->getVerbose(), bundle->getForce()); 139 //for (int i = 0; i < bundle->getFileSpecCount(); i++) 140 // printf(" %d: '%s'\n", i, bundle->getFileSpecEntry(i)); 141 142 switch (bundle->getCommand()) { 143 case kCommandVersion: return doVersion(bundle); 144 case kCommandList: return doList(bundle); 145 case kCommandDump: return doDump(bundle); 146 case kCommandAdd: return doAdd(bundle); 147 case kCommandRemove: return doRemove(bundle); 148 case kCommandPackage: return doPackage(bundle); 149 default: 150 fprintf(stderr, "%s: requested command not yet supported\n", gProgName); 151 return 1; 152 } 153} 154 155/* 156 * Parse args. 157 */ 158int main(int argc, char* const argv[]) 159{ 160 char *prog = argv[0]; 161 Bundle bundle; 162 bool wantUsage = false; 163 int result = 1; // pessimistically assume an error. 164 int tolerance = 0; 165 166 /* default to compression */ 167 bundle.setCompressionMethod(ZipEntry::kCompressDeflated); 168 169 if (argc < 2) { 170 wantUsage = true; 171 goto bail; 172 } 173 174 if (argv[1][0] == 'v') 175 bundle.setCommand(kCommandVersion); 176 else if (argv[1][0] == 'd') 177 bundle.setCommand(kCommandDump); 178 else if (argv[1][0] == 'l') 179 bundle.setCommand(kCommandList); 180 else if (argv[1][0] == 'a') 181 bundle.setCommand(kCommandAdd); 182 else if (argv[1][0] == 'r') 183 bundle.setCommand(kCommandRemove); 184 else if (argv[1][0] == 'p') 185 bundle.setCommand(kCommandPackage); 186 else { 187 fprintf(stderr, "ERROR: Unknown command '%s'\n", argv[1]); 188 wantUsage = true; 189 goto bail; 190 } 191 argc -= 2; 192 argv += 2; 193 194 /* 195 * Pull out flags. We support "-fv" and "-f -v". 196 */ 197 while (argc && argv[0][0] == '-') { 198 /* flag(s) found */ 199 const char* cp = argv[0] +1; 200 201 while (*cp != '\0') { 202 switch (*cp) { 203 case 'v': 204 bundle.setVerbose(true); 205 break; 206 case 'a': 207 bundle.setAndroidList(true); 208 break; 209 case 'c': 210 argc--; 211 argv++; 212 if (!argc) { 213 fprintf(stderr, "ERROR: No argument supplied for '-c' option\n"); 214 wantUsage = true; 215 goto bail; 216 } 217 bundle.addConfigurations(argv[0]); 218 break; 219 case 'f': 220 bundle.setForce(true); 221 break; 222 case 'g': 223 argc--; 224 argv++; 225 if (!argc) { 226 fprintf(stderr, "ERROR: No argument supplied for '-g' option\n"); 227 wantUsage = true; 228 goto bail; 229 } 230 tolerance = atoi(argv[0]); 231 bundle.setGrayscaleTolerance(tolerance); 232 printf("%s: Images with deviation <= %d will be forced to grayscale.\n", prog, tolerance); 233 break; 234 case 'm': 235 bundle.setMakePackageDirs(true); 236 break; 237#if 0 238 case 'p': 239 bundle.setPseudolocalize(true); 240 break; 241#endif 242 case 'u': 243 bundle.setUpdate(true); 244 break; 245 case 'x': 246 bundle.setExtending(true); 247 break; 248 case 'z': 249 bundle.setRequireLocalization(true); 250 break; 251 case 'j': 252 argc--; 253 argv++; 254 if (!argc) { 255 fprintf(stderr, "ERROR: No argument supplied for '-j' option\n"); 256 wantUsage = true; 257 goto bail; 258 } 259 convertPath(argv[0]); 260 bundle.addJarFile(argv[0]); 261 break; 262 case 'A': 263 argc--; 264 argv++; 265 if (!argc) { 266 fprintf(stderr, "ERROR: No argument supplied for '-A' option\n"); 267 wantUsage = true; 268 goto bail; 269 } 270 convertPath(argv[0]); 271 bundle.setAssetSourceDir(argv[0]); 272 break; 273 case 'I': 274 argc--; 275 argv++; 276 if (!argc) { 277 fprintf(stderr, "ERROR: No argument supplied for '-I' option\n"); 278 wantUsage = true; 279 goto bail; 280 } 281 convertPath(argv[0]); 282 bundle.addPackageInclude(argv[0]); 283 break; 284 case 'F': 285 argc--; 286 argv++; 287 if (!argc) { 288 fprintf(stderr, "ERROR: No argument supplied for '-F' option\n"); 289 wantUsage = true; 290 goto bail; 291 } 292 convertPath(argv[0]); 293 bundle.setOutputAPKFile(argv[0]); 294 break; 295 case 'J': 296 argc--; 297 argv++; 298 if (!argc) { 299 fprintf(stderr, "ERROR: No argument supplied for '-J' option\n"); 300 wantUsage = true; 301 goto bail; 302 } 303 convertPath(argv[0]); 304 bundle.setRClassDir(argv[0]); 305 break; 306 case 'M': 307 argc--; 308 argv++; 309 if (!argc) { 310 fprintf(stderr, "ERROR: No argument supplied for '-M' option\n"); 311 wantUsage = true; 312 goto bail; 313 } 314 convertPath(argv[0]); 315 bundle.setAndroidManifestFile(argv[0]); 316 break; 317 case 'P': 318 argc--; 319 argv++; 320 if (!argc) { 321 fprintf(stderr, "ERROR: No argument supplied for '-P' option\n"); 322 wantUsage = true; 323 goto bail; 324 } 325 convertPath(argv[0]); 326 bundle.setPublicOutputFile(argv[0]); 327 break; 328 case 'S': 329 argc--; 330 argv++; 331 if (!argc) { 332 fprintf(stderr, "ERROR: No argument supplied for '-S' option\n"); 333 wantUsage = true; 334 goto bail; 335 } 336 convertPath(argv[0]); 337 bundle.addResourceSourceDir(argv[0]); 338 break; 339 case '0': 340 argc--; 341 argv++; 342 if (!argc) { 343 fprintf(stderr, "ERROR: No argument supplied for '-e' option\n"); 344 wantUsage = true; 345 goto bail; 346 } 347 if (argv[0][0] != 0) { 348 bundle.addNoCompressExtension(argv[0]); 349 } else { 350 bundle.setCompressionMethod(ZipEntry::kCompressStored); 351 } 352 break; 353 case '-': 354 if (strcmp(cp, "-min-sdk-version") == 0) { 355 argc--; 356 argv++; 357 if (!argc) { 358 fprintf(stderr, "ERROR: No argument supplied for '--min-sdk-version' option\n"); 359 wantUsage = true; 360 goto bail; 361 } 362 bundle.setMinSdkVersion(argv[0]); 363 } else if (strcmp(cp, "-target-sdk-version") == 0) { 364 argc--; 365 argv++; 366 if (!argc) { 367 fprintf(stderr, "ERROR: No argument supplied for '--target-sdk-version' option\n"); 368 wantUsage = true; 369 goto bail; 370 } 371 bundle.setTargetSdkVersion(argv[0]); 372 } else if (strcmp(cp, "-max-sdk-version") == 0) { 373 argc--; 374 argv++; 375 if (!argc) { 376 fprintf(stderr, "ERROR: No argument supplied for '--max-sdk-version' option\n"); 377 wantUsage = true; 378 goto bail; 379 } 380 bundle.setMaxSdkVersion(argv[0]); 381 } else if (strcmp(cp, "-version-code") == 0) { 382 argc--; 383 argv++; 384 if (!argc) { 385 fprintf(stderr, "ERROR: No argument supplied for '--version-code' option\n"); 386 wantUsage = true; 387 goto bail; 388 } 389 bundle.setVersionCode(argv[0]); 390 } else if (strcmp(cp, "-version-name") == 0) { 391 argc--; 392 argv++; 393 if (!argc) { 394 fprintf(stderr, "ERROR: No argument supplied for '--version-name' option\n"); 395 wantUsage = true; 396 goto bail; 397 } 398 bundle.setVersionName(argv[0]); 399 } else { 400 fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp); 401 wantUsage = true; 402 goto bail; 403 } 404 cp += strlen(cp) - 1; 405 break; 406 default: 407 fprintf(stderr, "ERROR: Unknown flag '-%c'\n", *cp); 408 wantUsage = true; 409 goto bail; 410 } 411 412 cp++; 413 } 414 argc--; 415 argv++; 416 } 417 418 /* 419 * We're past the flags. The rest all goes straight in. 420 */ 421 bundle.setFileSpec(argv, argc); 422 423 result = handleCommand(&bundle); 424 425bail: 426 if (wantUsage) { 427 usage(); 428 result = 2; 429 } 430 431 //printf("--> returning %d\n", result); 432 return result; 433} 434