| /* |
| * 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.AndroidPlatformTarget; |
| import com.google.common.base.Optional; |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| |
| import java.util.Set; |
| |
| /** |
| * 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 { |
| |
| private final String androidManifest; |
| private final Set<String> resDirectories; |
| private final Optional<String> assetsDirectory; |
| private final String pathToOutputApkFile; |
| private final Set<String> pathsToRawFilesDirs; |
| |
| @SuppressWarnings("unused") |
| private final boolean isCrunchPngFiles; |
| |
| public AaptStep( |
| String androidManifest, |
| Set<String> resDirectories, |
| Optional<String> assetsDirectory, |
| String pathToOutputApkFile, |
| Set<String> pathsToRawFilesDirs, |
| boolean isCrunchPngFiles) { |
| this.androidManifest = Preconditions.checkNotNull(androidManifest); |
| this.resDirectories = ImmutableSet.copyOf(resDirectories); |
| this.assetsDirectory = Preconditions.checkNotNull(assetsDirectory); |
| this.pathToOutputApkFile = Preconditions.checkNotNull(pathToOutputApkFile); |
| this.pathsToRawFilesDirs = ImmutableSet.copyOf(pathsToRawFilesDirs); |
| this.isCrunchPngFiles = isCrunchPngFiles; |
| } |
| |
| @Override |
| protected ImmutableList<String> getShellCommandInternal(ExecutionContext context) { |
| ImmutableList.Builder<String> builder = ImmutableList.builder(); |
| |
| AndroidPlatformTarget androidPlatformTarget = context.getAndroidPlatformTarget(); |
| builder.add(androidPlatformTarget.getAaptExecutable().getAbsolutePath(), "package"); |
| |
| // verbose flag, if appropriate. |
| if (context.getVerbosity().shouldUseVerbosityFlagIfAvailable()) { |
| builder.add("-v"); |
| } |
| |
| // Force overwrite of existing files. |
| builder.add("-f"); |
| |
| /* |
| * In practice, it appears that if --no-crunch is used, resources will occasionally appear |
| * distorted in the APK produced by this command (and what's worse, a clean reinstall does not |
| * make the problem go away). This is not reliably reproducible, so for now, we categorically |
| * outlaw the use of --no-crunch so that developers do not get stuck in the distorted image |
| * state. One would expect the use of --no-crunch to allow for faster build times, so it would |
| * be nice to figure out a way to leverage it in debug mode that never results in distorted |
| * images. |
| */ |
| // --no-crunch, if appropriate. |
| // if (!isCrunchPngFiles) { |
| // builder.add("--no-crunch"); |
| // } |
| |
| // Include all of the res/ directories. |
| builder.add("--auto-add-overlay"); |
| for (String res : resDirectories) { |
| builder.add("-S", res); |
| } |
| |
| // 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()); |
| } |
| |
| builder.add("-M").add(androidManifest); |
| builder.add("-I", androidPlatformTarget.getAndroidJar().getAbsolutePath()); |
| builder.add("-F", pathToOutputApkFile); |
| |
| builder.addAll(pathsToRawFilesDirs); |
| |
| return builder.build(); |
| } |
| |
| @Override |
| public String getShortName() { |
| return String.format("aapt_package"); |
| } |
| |
| } |