| /* |
| * Copyright 2012-present Facebook, Inc. |
| * |
| * 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. |
| */ |
| |
| package com.facebook.buck.android; |
| |
| import com.android.sdklib.build.ApkBuilder; |
| import com.facebook.buck.shell.ShellStep; |
| import com.facebook.buck.step.ExecutionContext; |
| import com.facebook.buck.util.MoreStrings; |
| import com.google.common.base.Optional; |
| import com.google.common.collect.ImmutableList; |
| |
| import java.nio.file.Path; |
| |
| /** |
| * Runs the Android Asset Packaging Tool ({@code aapt}), which creates an {@code .apk} file. |
| * Frequently, the {@code pathsToRawFilesDirs} excludes {@code classes.dex}, as {@code classes.dex} |
| * will be added separately to the final APK via {@link ApkBuilder}. |
| */ |
| public class AaptStep extends ShellStep { |
| |
| // aapt, unless specified a pattern, ignores certain files and directories. We follow the same |
| // logic as the default pattern found at http://goo.gl/OTTK88 and line 61. |
| private static final String DEFAULT_IGNORE_ASSETS_PATTERN = |
| "\\!.svn:\\!.git:\\!.ds_store:\\!*.scc:.*:<dir>_*:\\!CVS:\\!thumbs.db:\\!picasa.ini:\\!*~"; |
| |
| // Ignore *.orig files generated by mercurial. |
| public static final String IGNORE_ASSETS_PATTERN = DEFAULT_IGNORE_ASSETS_PATTERN + ":*.orig"; |
| |
| /** |
| * Determines whether the default AAPT ignore pattern in |
| * {@link com.facebook.buck.android.AaptStep#DEFAULT_IGNORE_ASSETS_PATTERN} |
| * would silently ignore a file. |
| * |
| * @param path The path of the file we are interested in. |
| * @return Whether the file would be silently ignored. |
| */ |
| public static boolean isSilentlyIgnored(Path path) { |
| String fileName = path.getFileName().toString(); |
| return |
| ".svn".equalsIgnoreCase(fileName) || |
| ".git".equalsIgnoreCase(fileName) || |
| ".ds_store".equalsIgnoreCase(fileName) || |
| MoreStrings.endsWithIgnoreCase(fileName, ".scc") || |
| "cvs".equalsIgnoreCase(fileName) || |
| "thumbs.db".equalsIgnoreCase(fileName) || |
| "picasa.ini".equalsIgnoreCase(fileName) || |
| fileName.endsWith("~"); |
| } |
| |
| private final Path androidManifest; |
| private final ImmutableList<Path> resDirectories; |
| private final Optional<Path> assetsDirectory; |
| private final Path pathToOutputApkFile; |
| private final Path pathToRDotTxtDir; |
| private final Optional<Path> pathToGeneratedProguardConfig; |
| |
| private final boolean isCrunchPngFiles; |
| |
| public AaptStep( |
| Path androidManifest, |
| ImmutableList<Path> resDirectories, |
| Optional<Path> assetsDirectory, |
| Path pathToOutputApkFile, |
| Path pathToRDotTxtDir, |
| Optional<Path> pathToGeneratedProguardConfig, |
| boolean isCrunchPngFiles) { |
| this.androidManifest = androidManifest; |
| this.resDirectories = resDirectories; |
| this.assetsDirectory = assetsDirectory; |
| this.pathToOutputApkFile = pathToOutputApkFile; |
| this.pathToRDotTxtDir = pathToRDotTxtDir; |
| this.pathToGeneratedProguardConfig = pathToGeneratedProguardConfig; |
| this.isCrunchPngFiles = isCrunchPngFiles; |
| } |
| |
| @Override |
| protected ImmutableList<String> getShellCommandInternal(ExecutionContext context) { |
| ImmutableList.Builder<String> builder = ImmutableList.builder(); |
| AndroidPlatformTarget androidPlatformTarget = context.getAndroidPlatformTarget(); |
| |
| builder.add(androidPlatformTarget.getAaptExecutable().toString()); |
| builder.add("package"); |
| |
| // verbose flag, if appropriate. |
| if (context.getVerbosity().shouldUseVerbosityFlagIfAvailable()) { |
| builder.add("-v"); |
| } |
| |
| // Force overwrite of existing files. |
| builder.add("-f"); |
| |
| if (pathToGeneratedProguardConfig.isPresent()) { |
| builder.add("-G", pathToGeneratedProguardConfig.get().toString()); |
| } |
| |
| // --no-crunch, if appropriate. |
| if (!isCrunchPngFiles) { |
| builder.add("--no-crunch"); |
| } |
| |
| // Include all of the res/ directories. |
| builder.add("--auto-add-overlay"); |
| for (Path res : resDirectories) { |
| builder.add("-S", res.toString()); |
| } |
| |
| // Include the assets/ directory, if any. |
| // According to the aapt documentation, it appears that it should be possible to specify the -A |
| // flag multiple times; however, in practice, when it is specified multiple times, only one of |
| // the folders is included in the final APK. |
| if (assetsDirectory.isPresent()) { |
| builder.add("-A", assetsDirectory.get().toString()); |
| } |
| |
| builder.add("--output-text-symbols").add(pathToRDotTxtDir.toString()); |
| builder.add("-J").add(pathToRDotTxtDir.toString()); |
| |
| builder.add("-M").add(androidManifest.toString()); |
| builder.add("-I", androidPlatformTarget.getAndroidJar().toString()); |
| builder.add("-F", pathToOutputApkFile.toString()); |
| |
| builder.add("--ignore-assets", IGNORE_ASSETS_PATTERN); |
| |
| return builder.build(); |
| } |
| |
| @Override |
| public String getShortName() { |
| return String.format("aapt_package"); |
| } |
| |
| } |