升级Android Studio的Gradle插件到3.0.1和Gradle到4.1之后,无法复制配置依赖项。

80

我曾经使用这个简单的Gradle任务将“编译”依赖项复制到特定文件夹:

task copyLibs(type: Copy) {
    from configurations.compile
    into "$project.rootDir/reports/libs/"
}

我的Android项目使用gradle插件3.0.1和Gradle工具4.1升级后停止工作了。由于依赖配置'compile'现在已被弃用,详情请参见https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#new_configurations,我将其更改为'implementation'。但是根据Gradle构建错误输出,我无法直接使用解决配置'implementation',因此无法使用我的copyLibs任务。

$ ./gradlew.bat clean build

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':app:copyLibs'.
> Resolving configuration 'implementation' directly is not allowed

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s

以下是我的当前app模块的build.gradle文件:apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "newgradle.com.testingnewgradle"
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support:support-v4:26.1.0'
    implementation 'com.android.support:design:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

task copyLibs(type: Copy) {
    from configurations.implementation
    into "$project.rootDir/reports/libs/"
}
build.dependsOn copyLibs

如果我使用“编译”,它可以工作,但我想遵循这个插件的最新建议。

我需要帮助升级我的copyLibs任务,以便在升级我的环境之前像以前一样工作。我曾经使用过Android Studio的gradle插件2.2.3和Gradle工具2.14.1。


请注意,同事在https://discuss.gradle.org/t/not-able-to-copy-implementation-dependencies/25344上提出了一张票据。 - Rafael
7个回答

92

与其使用configurations.implementation,最好的选择是使用configurations.runtimeClasspath

您也可以考虑: compileClasspath default


18
实际上,这是一种更为优雅的解决方案。只需将 configurations.compile 替换为 configurations.compileClasspath 即可完美解决问题(至少对于我而言)。 - racs
17
它说:“在类型为org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer的配置容器中,无法获取未知属性'runtimeClasspath'。”我错过了什么?'compileClasspath'也是一样。我的代码看起来与之前的代码相同,只是它是一个库而不是应用程序。 - kristyna
@Bot 已经过去了几个月,所以我不太记得我是怎么解决的了。我需要在Maven/Artifactory中包含所有依赖项,现在这对我来说已经起作用了。你到底想要实现什么? - kristyna
@kristyna,我将Gradle插件升级到3.1.2版本,现在它可以正常工作了。感谢您的回复。 - Bot
1
configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } 对于我来说很有效(适用于Android java-library)。 - Ivan
我也遇到了一个问题,即无法获取类型为org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer的配置容器的未知属性'runtimeClasspath'。相反,使用设置configurations.implementation.setCanBeResolved(true)的解决方案对我有用。 - Michał Powłoka

32

我使配置可解析,因此在获取依赖项时不会发生异常

configurations.implementation.setCanBeResolved(true)
configurations.api.setCanBeResolved(true)

println configurations.implementation.resolve()
println configurations.api.resolve()

这是我认为最干净的解决方案!+1 - curd0
8
你会把这段代码放在哪个build.gradle文件中?当我尝试添加它时,我一直收到错误信息> Cannot change strategy of configuration ':app:api' after it has been resolved. - Destiny Faith
1
嗨,在任何任务中,比如这个,在另一个配置前面或者只是在 :): 前面: 任务复制Android本地文件() { ... 配置.implementation.setCanBeResolved(true) 配置.api.setCanBeResolved(true) 配置.... - Iefimenko Ievgen
1
setCanBeResolved(true)现在已被弃用,并计划在Gradle 9.0中移除。 - undefined

16

另一个建议。

我创建了自定义配置,然后将其用作 configurations.customConfig

configurations {
  customConfig.extendsFrom implementation
}

复制任务必须相应地进行编辑:

task copyLibs(type: Copy) {
    from configurations.customConfig
    into "$project.rootDir/reports/libs/"
}

我对这个解决方案非常怀疑,但它实际上是有效的。 - dora2010
1
我明白这实际上是正确的解决方案。Gradle 6.4已经建议 [...] Resolving dependency configuration 'implementation' is not allowed as it is defined as 'canBeResolved=false'. Instead, a resolvable ('canBeResolved=true') dependency configuration that extends 'implementation' should be resolved. 相应的任务 copyLibs 将从 configurations.customConfig 复制。 - Alberto
它不应该是 from configuration.customConfig 吗? - Chris Watts
应该的。谢谢。 - mortalis

9
似乎没有办法获取实现依赖项列表和compileClasspath,而在Gradle ticket中提到的 Rafael 帖子对于直接使用 Android(像我这样)的情况不起作用,我需要导出依赖项以便Unity3D可以将它们打包发布。因此,看起来在这种情况下唯一的解决方案是使用已弃用的“编译”类型。

7
这可能不会有太大的帮助或更好的解决方案,但是……
您可以按照以下方式将依赖项放置在可复制的位置:
android { ... }

// Add a new configuration to hold your dependencies
configurations {
    myConfig
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support:support-v4:26.1.0'
    implementation 'com.android.support:design:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    // Now you have to repeat adding the dependencies you want to copy in the 'myConfig'
    myConfig fileTree(dir: 'libs', include: ['*.jar'])
    myConfig 'com.android.support:appcompat-v7:26.1.0'
    myConfig 'com.android.support:support-v4:26.1.0'
    ...
}

task copyLibs(type: Copy) {
    // Now you can use 'myConfig' instead of 'implementation' or 'compile' 
    from configurations.myConfig 
    into "$project.rootDir/reports/libs/"
}

如果您有一个Jar任务,它停止将依赖项放入jar文件,因为您从compile切换到implementation,那么这也是有用的。

您可以使用:

from {configurations.myConfig.collect { it.isDirectory() ? it : zipTree(it) }}

改为:

from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}

1
使用 classpath 'com.android.tools.build:gradle:3.2.1'distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip。我不确定它是否仍然有效... - Damiii
如果您按照您所建议的做法进行操作,应该会收到某种重复错误,例如“重复类android.arch.core.internal.SafeIterableMap”。 - portfoliobuilder

0

我在从gradle 5.5升级到5.6后开始遇到这个错误,当我尝试在intelliJ中同步项目时发生。

感谢另一个问题上的答案,我通过将idea 插件应用于所有项目,然后运行gradle cleanIdea解决了它,之后一切都重新开始工作了。

又是另一天,又有了一个难以解释的问题解决方案。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接