我使用 webpack 来构建我的应用程序(使用angular),命令: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 android@3.2'.
""")
}
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)
答案 0 :(得分:0)
真正的解决方案是将所有依赖项保留在同一版本中,除非您确实需要旧版本。因此,请确保所有支持库都在26.0.0-alpha1或您想要的任何级别。
替代解决方案:
转到Android清单并添加以下行:
工具:replace =“android:value”到元数据元素。它告诉android你要用什么库来构建。
答案 1 :(得分:0)
我找到了解决问题的方法。 triniwiz帮助了我,感谢他和你。这是解决方案的the link。再次感谢
triniwiz
所以看起来你有几个使用不同版本的插件 支持lib,以便您可以尝试以下方法来锁定支持 它将它锁定到最新版本你可以选择你的版本 想要使用该应用程序也需要将其放入 app.gradle位于/SomeApp/app/App_Resources/Android/app.gradle
repositories {maven { 网址&#39; https://maven.google.com&#39; }}
configurations.all {resolutionStrategy.eachDependency { DependencyResolveDetails详细信息 - &gt; def requested = details.requested if(requested.group ==&#39; com.android.support&#39;){ if(!requested.name.startsWith(&#34; multidex&#34;)){ details.useVersion&#39; 27.0.2&#39; } }
}}