无法使用发布标记构建我的应用程序

问题描述 投票:0回答:2

我使用webpack构建我的应用程序(带角度),命令:npm run build-android-bundle - uglify工作得很好,但是当我使用标志--release(npm run build-android-bundle - --release --keyStorePath~ / path / to / keystore --keyStorePassword your-pass --keyStoreAlias your-alias --keyStoreAliasPassword your-alias-pass)这里发生的错误是它的内容:

    Running full build
        ~/platforms/android/src/F0/AndroidManifest.xml:27:9-31 Error:
            Attribute meta-data#android.support.VERSION@value value=(25.3.1) from [com.android.support:design:25.3.1] AndroidManifest.xml:27:9-31
            is also present at [com.android.support:appcompat-v7:26.0.0-alpha1] AndroidManifest.xml:27:9-38 value=(26.0.0-alpha1).
            Suggestion: add 'tools:replace="android:value"' to <meta-data> element at AndroidManifest.xml:25:5-27:34 to override.

    FAILURE: Build failed with an exception.

    * What went wrong:
    Execution failed for task ':processF0F1F2F3ReleaseManifest'.
    > Manifest merger failed : Attribute meta-data#android.support.VERSION@value value=(25.3.1) from [com.android.support:design:25.3.1] AndroidManifest.xml:27:9-31
            is also present at [com.android.support:appcompat-v7:26.0.0-alpha1] AndroidManifest.xml:27:9-38 value=(26.0.0-alpha1).
            Suggestion: add 'tools:replace="android:value"' to <meta-data> element at AndroidManifest.xml:25:5-27:34 to override.  
Command ./gradlew failed with exit code 1

我想要帮助!

我的build.gradle文件:

import groovy.json.JsonSlurper

import java.nio.file.Files;
import java.nio.file.Paths;

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath "com.android.tools.build:gradle:2.2.3"
    }
}

apply plugin: "com.android.application"

def metadataParams = new LinkedList <String> ()
def allJarPaths = new LinkedList <String> ()
def configStage = "\tconfig phase: "
def nodeModulesDir = "../../node_modules/"
def dependenciesJson = file("dependencies.json")

// the build script will not work with previous versions of the CLI (3.1 or earlier)
if (!dependenciesJson.exists()) {
    throw new BuildCancelledException("""
'dependencies.json' file not found. Check whether the NativeScript CLI has prepared the project beforehand,
and that your NativeScript version is 3.3, or a more recent one. To build an android project with the current
version of the {N} CLI install a previous version of the runtime package - 'tns platform add [email protected]'.
""")
}

def nativescriptDependencies = new JsonSlurper().parseText(dependenciesJson.text)

def packageJsonContents = [:]

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 computeCompileSdkVersion = { -> project.hasProperty("compileSdk") ? compileSdk : 23 }
def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk : 23 }
def computeBuildToolsVersion = { -> project.hasProperty("buildToolsVersion") ? buildToolsVersion : "25.0.2" }

project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug"

def renameResultApks = { variant ->
    def name
    variant.outputs.each { output ->
        def apkDirectory = output.packageApplication.outputFile.parentFile
        def abiName = "";
        if (output.getFilter(com.android.build.OutputFile.ABI)) {
            abiName = "-" + output.getFilter(com.android.build.OutputFile.ABI);
        }
        def apkNamePrefix = rootProject.name + "-" + variant.buildType.name + abiName
        name = apkNamePrefix + ".apk"
        output.packageApplication.outputFile = new File(apkDirectory, name);
    }
}

////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATIONS ///////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

def applyPluginsIncludeGradleConfigurations =  { ->
    def taskNames = project.getGradle().startParameter.taskNames

    // don't apply plugin configurations if clean is invoked
    if (taskNames && taskNames.size() > 0 && taskNames.getAt(0).equals("clean")) {
        return []
    }

    def configurationsDir = new File(projectDir, "build/configurations")
    configurationsDir.deleteDir()

    def dimensions = []
    def includes = new ArrayList<String>()
    def flavorNumber = 0

    nativescriptDependencies.each { dep ->
        def androidDir = file("${dep.directory}/platforms/android")
        if (!androidDir.exists()) {
            return
        }

        def packageJsonPath = file("${dep.directory}/package.json")
        def packageJson = new JsonSlurper().parseText(packageJsonPath.text)
        def pluginName = packageJson.name
        def dimensionName = sanitizeDimensionName(pluginName)

        dimensions.add(dimensionName)
        def flavor = "F${flavorNumber++}"

        def includeGradleFile = new File(androidDir, "include.gradle")
        def destinationDir = file("${configurationsDir}/${pluginName}/")
        def destinationIncludeGradleFile = file("${configurationsDir}/${pluginName}/include.gradle")

        Files.createDirectories(Paths.get(destinationDir.getAbsolutePath()))

        if (includeGradleFile.exists()) {
            println "\t + add include.gradle from ${includeGradleFile}"
            destinationIncludeGradleFile.text = modifyProductFlavorInContent(includeGradleFile.text, dimensionName, flavor)
        } else {
            println "\t + creating include.gradle for plugin ${file(dep.directory)}"
            destinationIncludeGradleFile.text = createProductFlavorsContent(flavor, dimensionName)
        }

        includes.add(destinationIncludeGradleFile.getAbsolutePath());

        copyAndRenamePluginDirToFlavorName(androidDir, flavor);
    }

    includes.each {
        println "\t + applying plugin configuration from ${it}"
        apply from: it
    }

    return dimensions
}

def applyAppGradleConfiguration = { ->
    def pathToAppGradle = "$projectDir/../../app/App_Resources/Android/app.gradle"
    def appGradle = file(pathToAppGradle)
    if (appGradle.exists()) {
        println "\t + applying user-defined configuration from ${appGradle}"
        apply from: pathToAppGradle
    } else {
        println "\t + couldn't load user-defined configuration from ${appGradle}. File doesn't exist."
    }
}

android {
    compileSdkVersion computeCompileSdkVersion()
    buildToolsVersion computeBuildToolsVersion()

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion computeTargetSdkVersion()
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
    }

    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)

        // forces packaging of resources and assets AFTER producing metadata
        // Reference: https://github.com/NativeScript/android-runtime/issues/785

        // Ensure metadata has been built and copied in assets before packaging
        variant.outputs.each { output ->
            def abiName = "";
            if (output.getFilter(com.android.build.OutputFile.ABI)) {
                abiName = output.getFilter(com.android.build.OutputFile.ABI)
                def packageTask = project.tasks.findByName("package${output.name}")
                if (packageTask) {
                    packageTask.dependsOn(buildMetadata)
                }
            }
        }

        // Compile the Java sources AFTER the Java code-generation step is done
        def compileTask = project.tasks.findByName("compile${variantName}JavaWithJavac")
        if (compileTask) {
            compileTask.dependsOn("asbg:generateBindings")
        }
    }

    applyAppGradleConfiguration()

    def dimensions = applyPluginsIncludeGradleConfigurations()

    flavorDimensions(*dimensions)
}

repositories {
    jcenter()
    maven { url 'https://maven.google.com' }

    // used for local *.AAR files
    def pluginDependencies = nativescriptDependencies.collect { "${it.directory}/platforms/android" }
    pluginDependencies.add("libs/runtime-libs")

    flatDir {
        dirs pluginDependencies
    }
}

dependencies {
    def supportVer = "22.2.0";
    if (project.hasProperty("supportVersion")) {
        supportVer = supportVersion
    }

    compile "com.android.support:support-v4:$supportVer"
    compile "com.android.support:appcompat-v7:$supportVer"
    debugCompile "com.android.support:design:$supportVer"

    // take all jars within the libs dir
    compile fileTree(dir: "$projectDir/libs", include: ["**/*.jar"])
}

////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATION PHASE //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

task addNativeScriptRuntimePackageDependency {
    def useV8Symbols = nativescriptDependencies.any {
        def packageJsonPath = file("${it.directory}/package.json");
        def packageJson = new JsonSlurper().parseText(packageJsonPath.text);
        return packageJson.nativescript.useV8Symbols;
    }

    def runtime = useV8Symbols ? "nativescript-regular" : "nativescript-optimized";
    println "\t + adding nativescript runtime package dependency: $runtime"

    project.dependencies.add("compile", [name: runtime, ext: "aar"])
}

task addDependenciesFromNativeScriptPlugins {
    nativescriptDependencies.each { dep ->
        def aarFiles = fileTree(dir: file("${dep.directory}/platforms/android"), include: ["**/*.aar"])
        aarFiles.each { aarFile ->
            def length = aarFile.name.length() - 4
            def fileName = aarFile.name[0..<length]
            println "\t + adding aar plugin dependency: " + aarFile.getAbsolutePath()
            project.dependencies.add("compile", [name: fileName, ext: "aar"])
        }

        def jarFiles = fileTree(dir: file("${dep.directory}/platforms/android"), include: ["**/*.jar"])
        jarFiles.each { jarFile ->
            println "\t + adding jar plugin dependency: " + jarFile.getAbsolutePath()
        }

        project.dependencies.add("compile", jarFiles)
    }
}

static 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;
}

static 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;
    }
}

static def sanitizeDimensionName(str) {
    return str.replaceAll(/\W/, "")
}

static def modifyProductFlavorInContent(content, dimension, flavor) {
    def indexStart = content.indexOf("productFlavors");
    def index = indexStart  + "productFlavors".length();
    def indexEnd = -1;
    def nestedOpenBracketsCount = 0;

    while (index < content.length())
    {
        // print content[index];
        if (content[index] == "}")
        {
            nestedOpenBracketsCount--;

            if (nestedOpenBracketsCount == 0)
            {
                indexEnd = index;
                break;
            }
        }
        else if (content[index] == "{")
        {
            nestedOpenBracketsCount++;
        }

        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}"
        }
    }
}

def copyFolder(source, destination) {
    if (source.isDirectory()) {
        Files.createDirectories(destination.toPath());

        def sourceFiles = source.list();

        sourceFiles.each { file ->
            def srcFile = new File(source, file);
            def destFile = new File(destination, file);

            //Recursive function call
            copyFolder(srcFile, destFile);
        }
    }
    else {
        // Copy the file content from one place to another
        def fileName = source.getName()
        def extension = fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0 ? fileName.substring(fileName.lastIndexOf(".") + 1) : "";
        // exclude aars from package, as we've already included it in the compile dependencies, and don't want it taking up space
        if (extension == "aar") {
            return
        }

        Files.copy(source.toPath(), destination.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
    }
}

def copyAndRenamePluginDirToFlavorName(directory, flavor) {
    def targetDir = file("src/${flavor}")

    copyFolder(directory, targetDir)
}

task ensureMetadataOutDir {
    def outputDir = file("$projectDir/metadata/output/assets/metadata")
    outputDir.mkdirs()
}

////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// EXECUTUION PHASE /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

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 ->
            logger.info("Task: collectAllJars: dependency file: " + 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 {
        // 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())
        }

        workingDir "build-tools"
        main "-jar"

        logger.info("Task buildMetadata: Call metadata-generator.jar with arguments: " + metadataParams.toString().replaceAll(',', ''))
        args metadataParams.toArray()
    }

    doLast {
        copy {
            from "$projectDir/metadata/output/assets/metadata"
            into "$projectDir/src/main/assets/metadata"
        }
    }
}

task generateTypescriptDefinitions (type: JavaExec) {
    def paramz = new ArrayList<String>();
    def includeDirs = ["com.android.support", "/platforms/" + android.compileSdkVersion]

    doFirst {
        delete "build-tools/typings"

        workingDir "build-tools"

        main "-jar"

        paramz.add("dts-generator.jar");
        paramz.add("-input");

        for (String jarPath: project.jarFiles) {
            // don't generate typings for runtime jars and classes
            if (shouldIncludeDirForTypings(jarPath, includeDirs)) {
                paramz.add(jarPath);
            }
        }

        paramz.add("-output");
        paramz.add("typings");

        logger.info("Task generateTypescriptDefinitions: Call dts-generator.jar with arguments: " + paramz.toString().replaceAll(',', ''))
        args paramz.toArray();
    }
}

generateTypescriptDefinitions.onlyIf {
    project.hasProperty("generateTypings") && Boolean.parseBoolean(project.generateTypings)
}

static def shouldIncludeDirForTypings(path, includeDirs) {
    for (String p: includeDirs) {
        if (path.indexOf(p) > -1) {
            return true;
        }
    }

    return false;
}

task copyTypings {
    doLast {
        println "Copied generated typings to application root level. Make sure to import android.d.ts in reference.d.ts"

        copy {
            from "$projectDir/build-tools/typings"
            into "$projectDir/../../"
        }
    }
}

copyTypings.onlyIf { generateTypescriptDefinitions.didWork }

task validateAppIdMatch {
    doLast {
        def packageJsonFile = new File("$projectDir/../../package.json");
        def lineSeparator = System.getProperty("line.separator");

        if (packageJsonFile.exists() && !project.hasProperty("release")) {
            String content = packageJsonFile.getText("UTF-8")
            def jsonSlurper = new JsonSlurper()
            def packageJsonMap = jsonSlurper.parseText(content)

            if (packageJsonMap.nativescript.id != android.defaultConfig.applicationId) {
                def errorMessage = "${lineSeparator}WARNING: The Application identifier is different from the one inside 'package.json' file.$lineSeparator" +
                    "NativeScript CLI might not work properly.$lineSeparator" +
                    "Update the application identifier in package.json and app.gradle so that they match.";
                logger.error(errorMessage);
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// 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", generateTypescriptDefinitions)

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// EXECUTION ORDER /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

collectAllJars.dependsOn(ensureMetadataOutDir)
buildMetadata.dependsOn(collectAllJars)
generateTypescriptDefinitions.finalizedBy(copyTypings)

task buildapk {
    //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", "$projectDir/src/main/assets/metadata"
}

task deleteFlavors (type: Delete){
    doLast {
        def srcDir = new File("$projectDir/src")
        srcDir.listFiles().each({ f ->
            def dirName = f.getName()
            if (dirName != "main" &&
                    dirName != "debug" &&
                    dirName != "release")   {
                delete f
            }
        })
    }
}

task deleteGeneratedBindings(type: Delete) {
    delete "$projectDir/src/main/java/com/tns/gen"
}

buildapk.finalizedBy("validateAppIdMatch");
deleteMetadata.dependsOn(":asbg:clean")
deleteFlavors.dependsOn(deleteMetadata)
deleteGeneratedBindings.dependsOn(deleteFlavors)
clean.dependsOn(deleteGeneratedBindings)
android angular webpack nativescript
2个回答
0
投票

真正的解决方案是将所有依赖项保留在同一版本中,除非您确实需要旧版本。因此,请确保所有支持库都在26.0.0-alpha1或您想要的任何级别。

替代解决方案:

转到您的Android清单并添加以下行:

tools:replace =“android:value”到元数据元素。它告诉android你要用什么库来构建。


0
投票

我找到了解决问题的方法。 triniwiz帮助了我,感谢他和你。这里是the link的解决方案。再次感谢

triniwiz

所以看起来你有几个使用不同版本的支持lib的插件,所以你可以尝试以下来锁定它将锁定它的支持版本到最新你可以选择你希望应用程序使用哪个版本你也需要把它放在位于/SomeApp/app/App_Resources/Android/app.gradle的app.gradle中

存储库{maven {url'https://maven.google.com'}}

configurations.all {resolutionStrategy.eachDependency {DependencyResolveDetails details - > def requested = details.requested if(requested.group =='com.android.support'){if(!requested.name.startsWith(“multidex”)){details .useVersion '27 .0.2'}}

} }

© www.soinside.com 2019 - 2024. All rights reserved.