【问题标题】:Gradle/Maven/Android: Library-private dependency not found when library is used via mavenGradle/Maven/Android:通过 maven 使用库时未找到库私有依赖项
【发布时间】:2021-11-24 05:00:16
【问题描述】:

我有一个带有库模块的 SampleApp:

:app
:library

该库正在使用以下依赖项和以下代码:

implementation "com.google.android.gms:play-services-safetynet:17.0.1"

----

import android.content.Context
import com.google.android.gms.safetynet.SafetyNet

class ClassUsingSafetynet {
    fun trigger(context: Context) {
        SafetyNet.getClient(context)
    }
}

SampleApp 在某处调用trigger

val triggerClass = ClassUsingSafetynet()
triggerClass.trigger(context)

只要 SampleApp 直接声明它对库模块的依赖关系,就可以正常工作:

implementation project(path: ':library')

但是如果我将库 aar 部署到我的本地 maven 并相应地声明依赖项,如下所示:

implementation ('com.myapplication:library:1.0.3@aar') { transitive = true }

我收到以下崩溃

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/safetynet/SafetyNet;
        at com.library.ClassUsingSafetynet.trigger(ClassUsingSafetynet.kt:10)
        at com.myapplication.MainActivity.onCreate$lambda-0(MainActivity.kt:38)

这里是发布 gradle 任务:

afterEvaluate {
    publishing {
        publications {
            release(MavenPublication) {

                groupId 'com.myapplication'
                artifactId 'library'
                version '1.0.3'
                artifact 'build/outputs/aar/library-release.aar'

                pom.withXml {
                    def dependenciesNode = asNode().appendNode('dependencies')

                    configurations.api.allDependencies.each {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                    }
                }
            }
        }
        repositories {
            mavenLocal()
        }
    }
}

我尝试使用 api 而不是 implementation 作为 SafetyNet 依赖项。没有区别。

我尝试设置/不设置{transitive = true}。没有区别。

我尝试设置/不设置@aar。没有区别。

我试图不创建 pom 文件。没有区别。

暂时没有应用ProGuard。


对我来说特别奇怪的是“SafetyNet”是库的私有依赖项。我的应用甚至不需要知道它。

【问题讨论】:

    标签: android maven gradle dependency-management


    【解决方案1】:

    发布的 POM 文件需要声明库的所有运行时依赖项,而不仅仅是其 API 依赖项。换句话说,在向 POM 添加依赖项时需要使用以下内容:

        configurations.releaseRuntimeClasspath.allDependencies.each {
            // …
        }
    

    以下是误会:

    “SafetyNet”是库的私有依赖项。我的应用甚至不需要知道它。

    您的应用确实不必担心这种“私有依赖”,但它仍然必须(能够)在运行时将其提供给库——因为没有它库将无法工作,因为它仍然是库的依赖

    我已经用一个小的虚拟 Android 项目成功地测试了这个更改。如果您无法使用上述信息使您的构建工作,请告诉我;然后我可以在我的答案中添加一个独立的工作示例项目。


    也就是说,我想知道您为什么手动 (a) 指定已发布的工件并 (b) 创建 POM?以下应该自动工作(如上所述测试):

        release(MavenPublication) {
            groupId 'com.myapplication'
            artifactId 'library'
            version '1.0.3'
    
            from components.release
        }
    

    另见the docs

    【讨论】:

    • 嗨,很抱歉反应迟了,感谢您的回答。我将在下周对此进行测试,因为我现在必须专注于其他主题。我会尽快回到这里。
    • 嗨,刚刚试过,但似乎configurations.runtimeClasspath 仅适用于 java 项目 - 不适用于 android。我收到消息Could not get unknown property 'runtimeClasspath' for configuration container of type org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer.。我用谷歌搜索了一下,似乎runtimeClasspath 仅在不适用于 Android 的 gradle java 插件中可用。 [docs.gradle.org/current/javadoc/org/gradle/api/artifacts/…
    • 对不起,你是对的。我已经更新了我的答案,使其也可以与 Android 库一起使用。那里的相关配置可能是releaseRuntimeClasspath。但请注意,通常甚至不需要手动修改 POM 创建;我也在我的答案中添加了相应的注释。
    • 不错!!它终于按预期工作了。即使是带有from components.release 的速记版本,但要使其正常工作,我必须删除artifact 'build/outputs/aar/crypto-release.aar' 行。否则我会得到错误:multiple artifacts with the identical extension and classifier ('aar', 'null')。非常感谢,赏金是你的:)
    猜你喜欢
    • 1970-01-01
    • 2013-12-09
    • 2014-03-21
    • 2017-09-18
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    相关资源
    最近更新 更多