Whenever I try to build or run an android project I usually run into this problem.
FAILURE: Build failed with an exception.
- What went wrong: Execution failed for task ':processF0F1F2F3F4F5DebugResources'. com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/usr/local/Cellar/android-sdk/24.4.1_1/build-tools/23.0.2/aapt'' finished with non-zero exit value 1
Does anyone know why this problem occurs? I have been trying for a very long time to fix this and I cannot figure out how to do so.
I think this is the build.gradle file. Correct me if I am wrong. Hopefully this helps!
/*
* Script builds apk in release or debug mode
* To run:
* gradle buildapk -Prelease (release mode)
* gradle buildapk (debug mode -> default)
* Options:
* -Prelease //this flag will run build in release mode
* -PksPath=[path_to_keystore_file]
* -PksPassword=[password_for_keystore_file]
* -Palias=[alias_to_use_from_keystore_file]
* -Ppassword=[password_for_alias]
*
* -PtargetSdk=[target_sdk]
* -PbuildToolsVersion=[build_tools_version]
* -PsupportVersion=[support_version]
* -PcompileSdk=[compile_sdk_version]
* -PdontRunSbg=[true/false]
*/
import groovy.json.JsonSlurper //used to parse package.json
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:2.1.2"
}
}
apply plugin: "com.android.application"
def isWinOs = System.properties['os.name'].toLowerCase().contains('windows')
def metadataParams = new LinkedList <String> ()
def allJarPaths = new LinkedList <String> ()
def configurationsDir = "$projectDir/configurations"
def createPluginConfigFile = false
def configStage = "\n:config phase: "
def nodeModulesDir = "../../node_modules/"
def libDir = "$projectDir/../../lib/Android/"
def flavorNames = new ArrayList<String>()
def configDir = file(configurationsDir)
def packageJsonContents = [:]
def excludedDevDependencies = ['**/.bin/**']
def dontRunSbg = project.hasProperty("dontRunSbg");
def asbgProject = project(":asbg")
asbgProject.ext.outDir = new File("$projectDir", "src/main/java")
asbgProject.ext.jsCodeDir = new File("$projectDir", "src/main/assets/app")
def compiteCompileSdkVersion () {
if(project.hasProperty("compileSdk")) {
return compileSdk
}
else {
return 23
}
}
def computeTargetSdkVersion() {
if(project.hasProperty("targetSdk")) {
return targetSdk
}
else {
return 23
}
}
def computeBuildToolsVersion() {
if(project.hasProperty("buildToolsVersion")) {
return buildToolsVersion
}
else {
return "23.0.3"
}
}
project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug"
def renameResultApks (variant) {
def name
variant.outputs.each { output ->
def apkDirectory = output.packageApplication.outputFile.parentFile
def apkNamePrefix = rootProject.name + "-" + variant.buildType.name
if (output.zipAlign) {
name = apkNamePrefix + ".apk"
output.outputFile = new File(apkDirectory, name);
}
name = apkNamePrefix + "-unaligned.apk"
output.packageApplication.outputFile = new File(apkDirectory, name);
}
}
// gets the devDependencies declared in the package.json and excludes them from the build
task getDevDependencies << {
println "$configStage getDevDependencies"
String content = new File("$projectDir/../../package.json").getText("UTF-8")
def jsonSlurper = new JsonSlurper()
def packageJsonMap = jsonSlurper.parseText(content)
packageJsonContents = packageJsonMap.devDependencies;
packageJsonContents.each { entry ->
excludedDevDependencies.add(entry.key + '/platforms/android/**/*.jar')
}
}
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATIONS ///////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
android {
compileSdkVersion compiteCompileSdkVersion()
buildToolsVersion computeBuildToolsVersion()
defaultConfig {
minSdkVersion 17
targetSdkVersion computeTargetSdkVersion()
}
sourceSets.main {
jniLibs.srcDir "$projectDir/libs/jni"
}
signingConfigs {
release {
if(project.hasProperty("release")) {
if(project.hasProperty("ksPath") &&
project.hasProperty("ksPassword") &&
project.hasProperty("alias") &&
project.hasProperty("password"))
{
storeFile file(ksPath)
storePassword ksPassword
keyAlias alias
keyPassword password
}
}
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
applicationVariants.all { variant ->
renameResultApks(variant)
}
applicationVariants.all { variant ->
def variantName = variant.name.capitalize()
def compileSourcesTaskName = "compile${variantName}Sources"
def compileSourcesTask = project.tasks.findByName(compileSourcesTaskName)
def generateBuildConfigTask = variant.generateBuildConfig;
generateBuildConfigTask.finalizedBy(collectAllJars)
if(!dontRunSbg) {
collectAllJars.finalizedBy(setProperties)
}
compileSourcesTask.finalizedBy(buildMetadata)
}
}
repositories {
jcenter()
// used for local *.AAR files
flatDir {
dirs 'libs/aar'
}
}
dependencies {
def suppotVer = "22.2.0";
if(project.hasProperty("supportVersion")) {
suppotVer = supportVersion
}
compile "com.android.support:support-v4:$suppotVer"
compile "com.android.support:appcompat-v7:$suppotVer"
// take all jars within the libs dir
compile fileTree(dir: "$projectDir/libs", include: ["**/*.jar"])
// take all jars within the node_modules dir
compile fileTree(dir: nodeModulesDir, include: ["**/platforms/android/**/*.jar"], exclude: excludedDevDependencies)
//when gradle has aar support this will be preferred instead of addAarDependencies
// compile files("$rootDir/libs/aar") {
// builtBy 'copyAarDependencies'
// }
compile project(':runtime')
}
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATION PHASE //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
task pluginStructureCheck {
def ft = fileTree(dir: nodeModulesDir, include: ["**/platforms/android/**/*.*"], exclude: '**/.bin/**')
ft.files.each { f ->
def fileName = f.getName();
if(
!fileName.endsWith(".aar")
&&
!fileName.equals("include.gradle")
&&
!fileName.endsWith(".jar")
){
println "WARNING: The file: " + f + " is depricated, you can read more about what will be the expected plugin structure here: https://www.nativescript.org/blog/migrating-n-android-plugins-from-version-1.7-to-2.0"
}
}
}
def updateProductFlavorsContent(flavor, dimensionName, oldContent) {
def endIndex = oldContent.length() - 1;
def index = 0;
def newContent = "";
def level = -1;
def dimensionFound = false;
while(index <= endIndex) {
if(level == 0 && (oldContent[index] == '"' || oldContent[index] == "'")) {
def closingQuotes = oldContent.indexOf('"', index + 1);
if(closingQuotes == -1) {
closingQuotes = oldContent.indexOf("'", index + 1);
}
index = closingQuotes + 1;
newContent += "\"${flavor}\"";
continue;
}
if(oldContent[index] == "{") {
level++;
}
if(oldContent[index] == "}") {
level--;
}
if(level > 0) {
if(!dimensionFound && oldContent.indexOf("dimension", index) == index) {
newContent += "dimension \"${dimensionName}\"";
dimensionFound = true;
index += "dimension ".length();
def openingQuoutes = oldContent.indexOf('"', index);
if(openingQuoutes == -1) {
openingQuoutes = oldContent.indexOf("'", index);
}
def closingQuotes = oldContent.indexOf('"', openingQuoutes + 1);
if(closingQuotes == -1) {
closingQuotes = oldContent.indexOf("'", openingQuoutes + 1);
}
index = closingQuotes + 1;
}
}
newContent += oldContent[index];
index++;
}
return newContent;
}
def createProductFlavorsContent(flavor, dimensionName, includeAndroidContent = true)
{
if (includeAndroidContent)
{
def content = """
android {
productFlavors {
"${flavor}" {
dimension "${dimensionName}"
}
}
}
"""
return content;
}
else
{
def content = """
productFlavors {
"${flavor}" {
dimension "${dimensionName}"
}
}
"""
return content;
}
}
def createIncludeFile (filePath, flavor, dimensionName) {
println "\t + creating include.gradle file for ${filePath}"
def defaultIncludeFile = new File(filePath, "include.gradle")
defaultIncludeFile.text = createProductFlavorsContent(flavor, dimensionName);
}
def sanatizeDimensionName(str) {
return str.replaceAll(/\W/, "")
}
def replaceProductFlavorInContent(content, dimension, flavor)
{
def indexStart = content.indexOf("productFlavors");
def index = indexStart + "productFlavors".length();
def indexEnd = -1;
def nestedOpenBraketsCount = 0;
while (index < content.length())
{
// print content[index];
if (content[index] == "}")
{
nestedOpenBraketsCount--;
if (nestedOpenBraketsCount == 0)
{
indexEnd = index;
break;
}
}
else if (content[index] == "{")
{
nestedOpenBraketsCount++;
}
index++;
}
if (indexEnd != -1)
{
// full content of productFlavors { ... } -> the substring is parenthesis to parenthesis -> { ... }
def oldProductFlavorsText = content.substring(indexStart, indexEnd + 1);
def newProductFlavorsContent = updateProductFlavorsContent(flavor, dimension, oldProductFlavorsText);
return content.replace(oldProductFlavorsText, newProductFlavorsContent);
}
else
{
def androidContentExists = content.indexOf("android {") != -1;
def newProductFlavorsContent = createProductFlavorsContent(flavor, dimension, !androidContentExists);
if (androidContentExists)
{
return content.replace("android {", "android { ${newProductFlavorsContent}");
}
else
{
return "${newProductFlavorsContent} \t ${content}"
}
}
}
//make sure the include.gradle file, produced by the user, has only allowed characters in dimension attribute and remove any invalid characters if necessary
def updateIncludeGradleFile(targetFile, dimensionName, flavor)
{
def fileEntry = new File(targetFile.getAbsolutePath());
def content = fileEntry.text;
def replacedContent = replaceProductFlavorInContent(content, dimensionName, flavor);
fileEntry.text = replacedContent;
}
def renamePluginDirToFlavorName(directory, flavor)
{
def parentName = directory.getName();
def parentFile = new File("src", parentName);
if (parentFile.exists())
{
def targetDirName = new File("src", flavor);
println "Renaming plugin directory to flavor name: ${parentFile.getAbsolutePath()} -> ${targetDirName.getAbsolutePath()}";
parentFile.renameTo(targetDirName);
}
}
def flavorNumber = 0
task createDefaultIncludeFiles {
description "creates default include.gradle files for added plugins IF NECESSARY"
println "$configStage createDefaultIncludeFiles"
def ft = file(configurationsDir)
ft.listFiles().each { fl ->
if(fl.isDirectory()) {
def fileName = fl.name
def dimensionName = sanatizeDimensionName(fileName)
createPluginConfigFile = true
def foundIncludeFile = false
def flavor = "F" + flavorNumber++
println "\t+found plugins: " + fileName
fl.listFiles().each { subFile ->
if(subFile.name == "include.gradle") {
foundIncludeFile = true
updateIncludeGradleFile(subFile, dimensionName, flavor)
renamePluginDirToFlavorName(subFile.getParentFile(), flavor);
}
}
flavorNames.add('"' + dimensionName + '"')
if(!foundIncludeFile) {
createIncludeFile(fl.getAbsolutePath() , flavor, dimensionName)
renamePluginDirToFlavorName(fl, flavor);
}
}
}
}
task createPluginsConfigFile {
description "creates product flavor config file based on what plugins are added"
if(configDir.exists()) {
println "$configStage createPluginsConfigFile"
def flavorsFile = new File("$configurationsDir/include.gradle")
if(createPluginConfigFile) {
println "\t Creating product flavors include.gradle file in $configurationsDir folder..."
def flavors = flavorNames.join(", ")
def content = """
android {
flavorDimensions ${flavors}
}
"""
flavorsFile.text = content
}
}
}
task pluginExtend {
description "applies additional configuration"
def pathToAppGradle = "$projectDir/../../app/App_Resources/Android/app.gradle"
def appGradle = file(pathToAppGradle)
if(appGradle.exists()) {
apply from: pathToAppGradle
}
if(configDir.exists()) {
println "$configStage pluginExtend"
configDir.eachFileRecurse(groovy.io.FileType.FILES) {
if(it.name.equals('include.gradle')) {
println "\t+applying configuration from: " + it
apply from: it
}
}
}
}
//// doesn't work unless task is explicitly called (TODO: research configurations hook)
// addAarDependencies.dependsOn(copyAarDependencies)
// createDefaultIncludeFiles.dependsOn(addAarDependencies)
// createPluginsConfigFile.dependsOn(createDefaultIncludeFiles)
// pluginExtend.dependsOn(createPluginsConfigFile)
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// BEFORE EXECUTION /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// we need to copy all dependencies into a flat dir, as pointed by the repositories configurations at the top
task copyAarDependencies (type: Copy) {
println "$configStage copyAarDependencies"
from fileTree(dir: nodeModulesDir, include: ["**/*.aar"], exclude: '**/.bin/**').files
into "$projectDir/libs/aar"
}
task addAarDependencies << {
println "$configStage addAarDependencies"
// manually traverse all the locally copied AAR files and add them to the project compilation dependencies list
FileTree tree = fileTree(dir: "$projectDir/libs/aar", include: ["**/*.aar"])
tree.each { File file ->
// remove the extension of the file (.aar)
def length = file.name.length() - 4
def fileName = file.name[0..<length]
println "\t+adding dependency: " + file.getAbsolutePath()
project.dependencies.add("compile", [name: fileName, ext: "aar"])
}
}
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// EXECUTUION PHASE /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
task cleanLocalAarFiles(type: Delete) {
delete fileTree(dir: "$projectDir/libs/aar", include: ["*.aar"])
}
task ensureMetadataOutDir {
def outputDir = file("$projectDir/metadata/output/assets/metadata")
outputDir.mkdirs()
}
task collectAllJars {
description "gathers all paths to jar dependencies before building metadata with them"
def explodedAarDir = project.buildDir.getAbsolutePath() + "/intermediates/exploded-aar/"
def sdkPath = android.sdkDirectory.getAbsolutePath();
def androidJar = sdkPath + "/platforms/" + android.compileSdkVersion + "/android.jar"
doFirst {
configurations.compile.each { File dependencyFile ->
// println "\t+" + dependencyFile.getAbsolutePath()
allJarPaths.add(dependencyFile.getAbsolutePath())
}
allJarPaths.add(androidJar);
def ft = fileTree(dir: explodedAarDir, include: "**/*.jar")
ft.each { currentJarFile ->
allJarPaths.add(currentJarFile.getAbsolutePath())
}
metadataParams.add("metadata-generator.jar")
metadataParams.add("$projectDir/metadata/output/assets/metadata")
def jars = new LinkedList<File>()
for(def i = 0; i < allJarPaths.size(); i++) {
metadataParams.add(allJarPaths.get(i));
def f = new File(allJarPaths.get(i))
if (f.getName().endsWith(".jar")) {
jars.add(f)
}
}
asbgProject.ext.jarFiles = jars
}
}
task buildMetadata (type: JavaExec) {
description "builds metadata with provided jar dependencies"
inputs.files(allJarPaths)
inputs.dir("$buildDir/intermediates/classes")
outputs.files("metadata/output/assets/metadata/treeNodeStream.dat", "metadata/output/assets/metadata/treeStringsStream.dat", "metadata/output/assets/metadata/treeValueStream.dat")
doFirst {
workingDir "build-tools"
main "-jar"
// get compiled classes to pass to metadata generator
// these need to be called after the classes have compiled
def classesDir = "$buildDir/intermediates/classes"
def classesSubDirs = new File(classesDir).listFiles()
def selectedBuildType = project.ext.selectedBuildType
for (File subDir: classesSubDirs) {
if (!subDir.getName().equals(selectedBuildType)) {
def subDirBuildType = new File(subDir, selectedBuildType)
if (subDirBuildType.exists()) {
metadataParams.add(subDirBuildType.getAbsolutePath());
}
}
}
def classesDirBuildType = new File(classesDir, selectedBuildType)
if (classesDirBuildType.exists()) {
metadataParams.add(classesDirBuildType.getAbsolutePath())
}
args metadataParams.toArray()
}
doLast {
copy {
from "$projectDir/metadata/output/assets/metadata"
into "$projectDir/src/main/assets/metadata"
}
def files = new File("${buildDir}/intermediates/res").listFiles()
def tmpResourceAPK = null
for (File f: files) {
def name = f.getName();
if (name.endsWith(".ap_")) {
tmpResourceAPK = f;
break;
}
}
def aaptCommand = "${android.getSdkDirectory().getAbsolutePath()}/build-tools/${android.buildToolsVersion}/aapt"
if (isWinOs) {
aaptCommand += ".exe"
}
def tmpAPKPath = tmpResourceAPK.getPath()
def removeCmdParams = new ArrayList<String>([aaptCommand, "remove", tmpAPKPath, "assets/metadata/treeNodeStream.dat", "assets/metadata/treeStringsStream.dat", "assets/metadata/treeValueStream.dat"])
exec {
ignoreExitValue true
workingDir "$projectDir/metadata/output"
commandLine removeCmdParams.toArray()
}
def addCmdParams = new ArrayList<String>([aaptCommand, "add", tmpAPKPath, "assets/metadata/treeNodeStream.dat", "assets/metadata/treeStringsStream.dat", "assets/metadata/treeValueStream.dat"])
exec {
workingDir "$projectDir/metadata/output"
commandLine addCmdParams.toArray()
}
}
}
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// OPTIONAL TASKS //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
task setProperties {
project.ext.jarFiles = []
doLast {
def list = [];
allJarPaths.each({f ->
if(f.endsWith(".jar")) {
list.add(f);
}
})
project.jarFiles = list;
}
}
setProperties.finalizedBy("asbg:generateBindings")
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// EXECUTION ORDER /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// -- configuration phase
// 1. Copy *.aar dependencies
// 2. Add *.aar dependencies
// 3. create default include files
// 4. create plugins config file
// 5. plugin extend (apply from include files)
// --execution phase
ensureMetadataOutDir.dependsOn(cleanLocalAarFiles)
collectAllJars.dependsOn(ensureMetadataOutDir)
buildMetadata.dependsOn(collectAllJars)
//DO NOT UNCOMMENT
// mergeAssets.dependsOn(copyMetadata) -> look in CONFIGURATIONS(top) in android.applicationVariants to see how it's done
task buildapk {
// problem is compile dependencies need to be changed before configuration stage
// and this is the only way so far
tasks.copyAarDependencies.execute()
tasks.addAarDependencies.execute()
//done to build only necessary apk
if(project.hasProperty("release")) {
dependsOn assembleRelease
}
else {
dependsOn assembleDebug
}
}
//////// custom clean ///////////
task deleteMetadata (type: Delete){
delete "$projectDir/metadata/output"
}
task deleteFlavors (type: Delete){
doLast {
def srcDir = new File("$projectDir/src")
srcDir.listFiles().each({ f ->
if(!f.getName().equals("main")) {
delete f
}
})
}
}
deleteFlavors.dependsOn(deleteMetadata)
clean.dependsOn(deleteFlavors)