0

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)
1
  • looks like a non valid string type in AndroidManifest.xml. There should be an other error message a few lines above of "*What went wrong". Could you post that? Commented Feb 9, 2017 at 12:07

1 Answer 1

0

Try going to build -> clean and also try rebuilding your project. Can you post your build.gradle file(s) if that doesn't work?

Sign up to request clarification or add additional context in comments.

6 Comments

Like the entire thing or part of it?
All of it, build.gradle shouldn't be that long. Did cleaning it not work?
You want the one that has the compileSdkVersion, buildToolsVersion etc.
That's a really weird gradle file, what IDE are you using? Does this problem come up for every project or just this one?
I am using a cross platform app called nativescript
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.