我是Android开发的新手。为此,我选择了NativeScript。
在一种情况下,我需要使用RadListView,因此将其插件添加到了我的应用程序中。但是当我尝试运行该应用程序时,出现此错误:
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all files for configuration ':app:debugCompileClasspath'.
> Could not find recyclerview-v7.jar (com.android.support:recyclerview-v7:28.0.0).
Searched in the following locations:
https://dl.google.com/dl/android/maven2/com/android/support/recyclerview-v7/28.0.0/recyclerview-v7-28.0.0.jar
如何复制:
> tns create my-app --template tns-template-hello-world
> cd my-app
> tns run android
> tns plugin add nativescript-ui-listview
> tns run android
第一个run
可以,第二个则不能。
最接近我的问题的页面是this。但是他可以通过升级gradle解决他的问题。我已经有了它的最新版本。
我的 build.gradle(根目录):
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
我的 build.gradle(应用程序):
/*
* Script builds apk in release or debug mode
* To run:
* gradle assembleRelease -Prelease (release mode)
* gradle assembleDebug (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]
*/
import groovy.json.JsonSlurper
import java.nio.file.Paths
import java.util.regex.Matcher
import java.util.regex.Pattern
apply plugin: "com.android.application"
def onlyX86 = project.hasProperty("onlyX86")
if (onlyX86) {
println "OnlyX86 build triggered."
}
//common
def BUILD_TOOLS_PATH = "$rootDir/build-tools"
def PASSED_TYPINGS_PATH = System.getenv("TNS_TYPESCRIPT_DECLARATIONS_PATH")
def TYPINGS_PATH = "$BUILD_TOOLS_PATH/typings"
if (PASSED_TYPINGS_PATH != null) {
TYPINGS_PATH = PASSED_TYPINGS_PATH
}
def USER_PROJECT_ROOT = "$rootDir/../.."
def PLATFORMS_ANDROID = "platforms/android"
def PACKAGE_JSON = "package.json"
//static binding generator
def SBG_JAVA_DEPENDENCIES = "sbg-java-dependencies.txt"
def SBG_INPUT_FILE = "sbg-input-file.txt"
def SBG_OUTPUT_FILE = "sbg-output-file.txt"
def SBG_JS_PARSED_FILES = "sbg-js-parsed-files.txt"
def SBG_BINDINGS_NAME = "sbg-bindings.txt"
def SBG_INTERFACE_NAMES = "sbg-interface-names.txt"
def INPUT_JS_DIR = "$projectDir/src/main/assets/app"
def OUTPUT_JAVA_DIR = "$projectDir/src/main/java"
//metadata generator
def MDG_OUTPUT_DIR = "mdg-output-dir.txt"
def MDG_JAVA_DEPENDENCIES = "mdg-java-dependencies.txt"
def METADATA_OUT_PATH = "$projectDir/src/main/assets/metadata"
// paths to jar libraries
def pluginsJarLibraries = new LinkedList<String>()
def allJarLibraries = new LinkedList<String>()
// the build script will not work with previous versions of the CLI (3.1 or earlier)
def dependenciesJson = file("$rootDir/dependencies.json")
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'.
""")
}
project.ext.extractedDependenciesDir = "${project.buildDir}/exploded-dependencies"
def nativescriptDependencies = new JsonSlurper().parseText(dependenciesJson.text)
def computeCompileSdkVersion = { -> project.hasProperty("compileSdk") ? compileSdk : 28 }
def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk : 28 }
def computeBuildToolsVersion = { ->
project.hasProperty("buildToolsVersion") ? buildToolsVersion : "28.0.3"
}
project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug"
project.ext.appResourcesPath = ""
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATIONS ///////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
def getAppResourcesPath = { ->
def relativePathToApp = "app"
def relativePathToAppResources
def absolutePathToAppResources
def nsConfigFile = file("$USER_PROJECT_ROOT/nsconfig.json")
def nsConfig
if (nsConfigFile.exists()) {
nsConfig = new JsonSlurper().parseText(nsConfigFile.getText("UTF-8"))
}
if(nsConfig != null && nsConfig.appPath != null){
relativePathToApp = nsConfig.appPath
}
if(nsConfig != null && nsConfig.appResourcesPath != null ) {
relativePathToAppResources = nsConfig.appResourcesPath
} else {
relativePathToAppResources = "$relativePathToApp/App_Resources"
}
absolutePathToAppResources = java.nio.file.Paths.get(USER_PROJECT_ROOT).resolve(relativePathToAppResources).toAbsolutePath()
project.ext.appResourcesPath = absolutePathToAppResources
return absolutePathToAppResources
}
def applyBeforePluginGradleConfiguration = { ->
def appResourcesPath = getAppResourcesPath()
def pathToBeforePluginGradle = "$appResourcesPath/Android/before-plugins.gradle"
def beforePluginGradle = file(pathToBeforePluginGradle)
if (beforePluginGradle.exists()) {
println "\t + applying user-defined configuration from ${beforePluginGradle}"
apply from: pathToBeforePluginGradle
}
}
def applyAppGradleConfiguration = { ->
def appResourcesPath = getAppResourcesPath()
def pathToAppGradle = "$appResourcesPath/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."
}
}
def applyPluginGradleConfigurations = { ->
nativescriptDependencies.each {dep ->
def includeGradlePath = "$rootDir/${dep.directory}/$PLATFORMS_ANDROID/include.gradle"
if(file(includeGradlePath).exists()) {
apply from: includeGradlePath
}
}
}
def getAppIdentifier = { packageJsonMap ->
def appIdentifier = "";
if (packageJsonMap && packageJsonMap.nativescript) {
appIdentifier = packageJsonMap.nativescript.id;
if (!(appIdentifier instanceof String)) {
appIdentifier = appIdentifier.android;
}
}
return appIdentifier;
}
def setAppIdentifier = { ->
println "\t + setting applicationId";
File packageJsonFile = new File("$rootDir/../../package.json");
if (packageJsonFile.exists()) {
def content = packageJsonFile.getText("UTF-8");
def jsonSlurper = new JsonSlurper();
def packageJsonMap = jsonSlurper.parseText(content);
def appIdentifier = getAppIdentifier(packageJsonMap);
if (appIdentifier) {
project.ext.nsApplicationIdentifier = appIdentifier;
android.defaultConfig.applicationId = appIdentifier;
}
}
}
android {
compileSdkVersion computeCompileSdkVersion()
buildToolsVersion computeBuildToolsVersion()
defaultConfig {
def manifest = new XmlSlurper().parse(file(android.sourceSets.main.manifest.srcFile))
def minSdkVer = manifest."uses-sdk"."@android:minSdkVersion".text() ?: 17
minSdkVersion minSdkVer
targetSdkVersion computeTargetSdkVersion()
ndk {
if (onlyX86) {
abiFilters 'x86'
} else {
abiFilters 'x86', 'armeabi-v7a'//, 'arm64-v8a'
}
}
dexOptions {
jumboMode = true
}
}
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
}
}
setAppIdentifier()
applyBeforePluginGradleConfiguration()
applyPluginGradleConfigurations()
applyAppGradleConfiguration()
}
def externalRuntimeExists = !findProject(':runtime').is(null)
repositories {
// used for local *.AAR files
def pluginDependencies = nativescriptDependencies.collect {
"$rootDir/${it.directory}/$PLATFORMS_ANDROID"
}
// some plugins may have their android dependencies in a /libs subdirectory
pluginDependencies.addAll(nativescriptDependencies.collect {
"$rootDir/${it.directory}/$PLATFORMS_ANDROID/libs"
})
if (!externalRuntimeExists) {
pluginDependencies.add("libs/runtime-libs")
}
def appResourcesPath = getAppResourcesPath()
def localAppResourcesLibraries = "$appResourcesPath/Android/libs"
pluginDependencies.add(localAppResourcesLibraries)
if (pluginDependencies.size() > 0) {
flatDir {
dirs pluginDependencies
}
}
}
dependencies {
def supportVer = "28.0.0"
if (project.hasProperty("supportVersion")) {
supportVer = supportVersion
}
println "Using support library version $supportVer"
implementation "com.android.support:multidex:1.0.2"
implementation "com.android.support:support-v4:$supportVer"
implementation "com.android.support:appcompat-v7:$supportVer"
implementation "com.android.support:design:$supportVer"
def sbgProjectExists = !findProject(':static-binding-generator').is(null)
if (sbgProjectExists) {
compileOnly project(':static-binding-generator')
}
def mdgProjectExists = !findProject(':android-metadata-generator').is(null)
if (mdgProjectExists) {
compileOnly project(':android-metadata-generator')
}
def dtsgProjectExists = !findProject(':dts-generator').is(null)
if (dtsgProjectExists) {
compileOnly project(':dts-generator')
}
def useV8Symbols = nativescriptDependencies.any {
def packageJsonPath = file("$rootDir/${it.directory}/$PACKAGE_JSON")
def packageJson = new JsonSlurper().parseText(packageJsonPath.text)
return packageJson.nativescript.useV8Symbols
}
if (!externalRuntimeExists) {
def runtime = "nativescript-optimized-with-inspector"
if (project.gradle.startParameter.taskNames.any { it.toLowerCase().contains('release') }) {
runtime = "nativescript-optimized"
}
if (useV8Symbols) {
runtime = "nativescript-regular"
}
println "\t + adding nativescript runtime package dependency: $runtime"
project.dependencies.add("implementation", [name: runtime, ext: "aar"])
} else {
implementation project(path: ':runtime', configuration: 'default')
}
}
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// CONFIGURATION PHASE //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
task addDependenciesFromNativeScriptPlugins {
nativescriptDependencies.each { dep ->
def aarFiles = fileTree(dir: file("$rootDir/${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("implementation", [name: fileName, ext: "aar"])
}
def jarFiles = fileTree(dir: file("$rootDir/${dep.directory}/$PLATFORMS_ANDROID"), include: ["**/*.jar"])
jarFiles.each { jarFile ->
def jarFileAbsolutePath = jarFile.getAbsolutePath()
println "\t + adding jar plugin dependency: $jarFileAbsolutePath"
pluginsJarLibraries.add(jarFile.getAbsolutePath())
}
project.dependencies.add("implementation", jarFiles)
}
}
task addDependenciesFromAppResourcesLibraries {
def appResourcesPath = getAppResourcesPath()
def appResourcesLibraries = file("$appResourcesPath/Android/libs")
if (appResourcesLibraries.exists()) {
def aarFiles = fileTree(dir: appResourcesLibraries, include: ["**/*.aar"])
aarFiles.each { aarFile ->
def length = aarFile.name.length() - 4
def fileName = aarFile.name[0..<length]
println "\t + adding aar library dependency: " + aarFile.getAbsolutePath()
project.dependencies.add("implementation", [name: fileName, ext: "aar"])
}
def jarFiles = fileTree(dir: appResourcesLibraries, include: ["**/*.jar"])
jarFiles.each { jarFile ->
def jarFileAbsolutePath = jarFile.getAbsolutePath()
println "\t + adding jar plugin dependency: $jarFileAbsolutePath"
pluginsJarLibraries.add(jarFile.getAbsolutePath())
}
project.dependencies.add("implementation", jarFiles)
}
}
tasks.whenTaskAdded({ org.gradle.api.DefaultTask currentTask ->
if (currentTask =~ /generate.+BuildConfig/) {
currentTask.finalizedBy(extractAllJars)
extractAllJars.finalizedBy(collectAllJars)
}
if (currentTask =~ /compile.+JavaWithJavac/) {
currentTask.dependsOn(runSbg)
currentTask.finalizedBy(ensureMetadataOutDir)
ensureMetadataOutDir.finalizedBy(buildMetadata)
}
if (currentTask =~ /assemble.*Debug/ || currentTask =~ /assemble.*Release/) {
currentTask.finalizedBy("validateAppIdMatch")
}
})
////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// EXECUTUION PHASE /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
task runSbg(type: JavaExec) {
inputs.dir(INPUT_JS_DIR)
workingDir "$BUILD_TOOLS_PATH"
main "-jar"
args "static-binding-generator.jar"
doFirst {
new File("$OUTPUT_JAVA_DIR/com/tns/gen").deleteDir();
}
}
task ensureMetadataOutDir {
doLast {
def outputDir = file("$METADATA_OUT_PATH")
outputDir.mkdirs()
}
}
def explodeAar(File compileDependency, String outputDir) {
if (compileDependency.name.endsWith(".aar")) {
java.util.jar.JarFile jar = new java.util.jar.JarFile(compileDependency)
Enumeration enumEntries = jar.entries()
while (enumEntries.hasMoreElements()) {
java.util.jar.JarEntry file = (java.util.jar.JarEntry) enumEntries.nextElement()
if (file.name.endsWith(".jar")) {
def f = new File(outputDir, file.name)
new File(f.parent).mkdirs()
InputStream is = jar.getInputStream(file)
FileOutputStream fos = new FileOutputStream(f)
while (is.available() > 0) {
fos.write(is.read())
}
fos.close()
is.close()
}
if (file.isDirectory()) {
continue
}
}
jar.close()
} else if (compileDependency.name.endsWith(".jar")) {
copy {
from compileDependency.absolutePath
into outputDir
}
}
}
task extractAllJars {
outputs.dir extractedDependenciesDir
doLast {
def buildType = project.selectedBuildType == "release" ? "Release" : "Debug"
def iter = []
Pattern pattern = Pattern.compile("^(.+)${buildType}CompileClasspath\$")
configurations.all{ config ->
Matcher matcher = pattern.matcher(config.name)
if (matcher.find() || config.name == "${buildType.toLowerCase()}CompileClasspath") {
config.resolve().each {
if (!iter.contains(it)) {
iter.push(it)
}
}
}
}
def dependencyCounter = 0
iter.each {
def nextDependency = it
def outputDir = java.nio.file.Paths.get(extractedDependenciesDir, "" + dependencyCounter).normalize().toString()
explodeAar(nextDependency, outputDir)
dependencyCounter++
}
}
}
task collectAllJars {
description "gathers all paths to jar dependencies before building metadata with them"
def sdkPath = android.sdkDirectory.getAbsolutePath()
def androidJar = sdkPath + "/platforms/" + android.compileSdkVersion + "/android.jar"
doFirst {
def allJarPaths = new LinkedList<String>()
allJarPaths.add(androidJar)
allJarPaths.addAll(pluginsJarLibraries)
def ft = fileTree(dir: extractedDependenciesDir, include: "**/*.jar")
ft.each { currentJarFile ->
allJarPaths.add(currentJarFile.getAbsolutePath())
}
new File("$BUILD_TOOLS_PATH/$SBG_JAVA_DEPENDENCIES").withWriter { out ->
allJarPaths.each { out.println it }
}
new File("$BUILD_TOOLS_PATH/$MDG_JAVA_DEPENDENCIES").withWriter { out ->
allJarPaths.each {
if (it.endsWith(".jar")) {
out.println it
}
}
}
new File("$BUILD_TOOLS_PATH/$SBG_INPUT_FILE").withWriter { out ->
out.println INPUT_JS_DIR
}
new File("$BUILD_TOOLS_PATH/$SBG_OUTPUT_FILE").withWriter { out ->
out.println OUTPUT_JAVA_DIR
}
allJarLibraries.addAll(allJarPaths)
}
}
task buildMetadata(type: JavaExec) {
description "builds metadata with provided jar dependencies"
inputs.files("$MDG_JAVA_DEPENDENCIES")
def classesDir = "$buildDir/intermediates/javac"
inputs.dir(classesDir)
outputs.files("$METADATA_OUT_PATH/treeNodeStream.dat", "$METADATA_OUT_PATH/treeStringsStream.dat", "$METADATA_OUT_PATH/treeValueStream.dat")
doFirst {
// get compiled classes to pass to metadata generator
// these need to be called after the classes have compiled
assert file(classesDir).exists()
def classesSubDirs = new File(classesDir).listFiles()
def selectedBuildType = project.ext.selectedBuildType
def generatedClasses = new LinkedList<String>()
for (File subDir : classesSubDirs) {
if (subDir.getName().equals(selectedBuildType)) {
generatedClasses.add(subDir.getAbsolutePath())
}
}
new File("$BUILD_TOOLS_PATH/$MDG_OUTPUT_DIR").withWriter { out ->
out.println "$METADATA_OUT_PATH"
}
new File("$BUILD_TOOLS_PATH/$MDG_JAVA_DEPENDENCIES").withWriterAppend { out ->
generatedClasses.each { out.println it }
}
workingDir "$BUILD_TOOLS_PATH"
main "-jar"
args "android-metadata-generator.jar"
}
}
task generateTypescriptDefinitions(type: JavaExec) {
def paramz = new ArrayList<String>()
def includeDirs = ["com.android.support", "/platforms/" + android.compileSdkVersion]
doFirst {
delete "$TYPINGS_PATH"
workingDir "$BUILD_TOOLS_PATH"
main "-jar"
paramz.add("dts-generator.jar")
paramz.add("-input")
for (String jarPath : allJarLibraries) {
// don't generate typings for runtime jars and classes
if (shouldIncludeDirForTypings(jarPath, includeDirs)) {
paramz.add(jarPath)
}
}
paramz.add("-output")
paramz.add("$TYPINGS_PATH")
new File("$TYPINGS_PATH").mkdirs()
logger.info("Task generateTypescriptDefinitions: Call dts-generator.jar with arguments: " + paramz.toString().replaceAll(',', ''))
println "Task generateTypescriptDefinitions: Call dts-generator.jar with arguments: " + paramz.toString().replaceAll(',', '')
args paramz.toArray()
}
}
generateTypescriptDefinitions.onlyIf {
(project.hasProperty("generateTypings") && Boolean.parseBoolean(project.generateTypings)) || PASSED_TYPINGS_PATH != null
}
collectAllJars.finalizedBy(generateTypescriptDefinitions)
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 "$TYPINGS_PATH"
into "$USER_PROJECT_ROOT"
}
}
}
copyTypings.onlyIf { generateTypescriptDefinitions.didWork }
generateTypescriptDefinitions.finalizedBy(copyTypings)
task validateAppIdMatch {
doLast {
def lineSeparator = System.getProperty("line.separator")
if (project.hasProperty("nsApplicationIdentifier") && !project.hasProperty("release")) {
if(project.nsApplicationIdentifier != 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" +
"Remove applicationId from app.gradle and update the \"nativescript.id\" in package.json.$lineSeparator" +
"Actual: ${android.defaultConfig.applicationId}$lineSeparator" +
"Expected(from \"package.json\"): ${project.nsApplicationIdentifier}$lineSeparator";
logger.error(errorMessage)
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// OPTIONAL TASKS //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
//////// custom clean ///////////
task cleanSbg(type: Delete) {
delete "$BUILD_TOOLS_PATH/$SBG_JS_PARSED_FILES",
"$BUILD_TOOLS_PATH/$SBG_JAVA_DEPENDENCIES",
"$BUILD_TOOLS_PATH/$SBG_INTERFACE_NAMES",
"$BUILD_TOOLS_PATH/$SBG_BINDINGS_NAME",
"$BUILD_TOOLS_PATH/$SBG_INPUT_FILE",
"$BUILD_TOOLS_PATH/$SBG_OUTPUT_FILE",
"$OUTPUT_JAVA_DIR/com/tns/gen"
}
task cleanMdg(type: Delete) {
delete "$BUILD_TOOLS_PATH/$MDG_OUTPUT_DIR",
"$BUILD_TOOLS_PATH/$MDG_JAVA_DEPENDENCIES",
"$METADATA_OUT_PATH"
}
cleanSbg.dependsOn(cleanMdg)
clean.dependsOn(cleanSbg)
我的 package.json(根):
{
"nativescript": {
"id": "org.nativescript.nativescriptrecyclerview",
"tns-android": {
"version": "5.0.0"
},
"tns-ios": {
"version": "5.0.0"
}
},
"description": "NativeScript Application",
"license": "SEE LICENSE IN <your-license-filename>",
"repository": "<fill-your-repository-here>",
"dependencies": {
"nativescript-theme-core": "~1.0.4",
"nativescript-ui-listview": "^5.0.1",
"tns-core-modules": "~5.0.2"
},
"devDependencies": {
"nativescript-dev-webpack": "~0.18.0"
},
"readme": "NativeScript Application"
}
来自Android Studio的Android SDK工具:
答案 0 :(得分:0)
这是来自Google Maven存储库的问题。 一些图书馆就消失了 这是Google问题跟踪器上的问题:https://issuetracker.google.com/issues/120759347
答案 1 :(得分:0)
在build.gradle中,这是新的实现
implementation 'androidx.recyclerview:recyclerview:1.0.0'
答案 2 :(得分:-2)
使用此链接https://developer.android.com/jetpack/androidx/migrate
将您的项目迁移到AndroidX在您的应用模块gradle文件中添加以下依赖项
implementation 'androidx.appcompat:appcompat:1.0.0'