如何修复 Android .aar 项目中的“java.lang.NoClassDefFoundError”

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

我构建了一个 android

.aar
库,我正在尝试将其与其中一个项目集成。当应用程序尝试打开
.aar
库的初始屏幕时,我在其中使用改造进行 API 调用。我收到以下异常

java.lang.NoClassDefFoundError:解决失败 of:Lokhttp3/OkHttpClient$Builder;

我没有在我的

.aar
项目中混淆或启用pro-guard。

下面是我的

.aar
Gradle 依赖项

implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.2.0'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
android retrofit2 okhttp aar
4个回答
15
投票

好吧,这是一个常见问题。在其他项目中使用 android 库(aar)有多种方法。例如:

  1. 通过使用以下命令将此 aar 作为模块导入到示例项目中
    implementation project(':mylibrary')
  2. 通过将 aar 上传到 Maven 存储库(artifactory、maven local、Jitpack 等)

注意这一点:

  1. 如果您使用上面的数字 1,那么您还必须 使用相同的方法将(retrofit、okhttp3等)添加到您的示例项目中 版本,因为默认情况下 aar 不包含子进程 依赖关系。这就是为什么你会得到这个例外 “java.lang.NoClassDefFoundError:无法解决以下问题: Lokhttp3/OkHttpClient$Builder'".
  2. 如果您使用上面的数字 2,那么您必须确保您的 pom.xml 文件包含您的子依赖项,因为服务器需要下载它们并在您的示例项目中提供它们。

我有什么推荐?

我建议开发人员使用

MavenLocal()
,它会在将 aar 发布到公共存储库(如 Jitpack 或任何你想要的东西)之前复制真实的场景。

我该怎么办?

  1. 在库模块的 build.gradle 中:

apply plugin: 'maven-publish'

project.afterEvaluate {
    publishing {
        publications {
            library(MavenPublication) {
                setGroupId 'YOUR_GROUP_ID'
                //You can either define these here or get them from project conf elsewhere
                setArtifactId 'YOUR_ARTIFACT_ID'
                version android.defaultConfig.versionName
                artifact bundleReleaseAar //aar artifact you want to publish

                pom.withXml {
                    def dependenciesNode = asNode().appendNode('dependencies')
                    configurations.implementation.allDependencies.each {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                    }
                }
            }
        }
    }
}

运行

assemble
publishToMavenLocal
gradle 任务。你会看到这样的东西:

  1. 在您的示例项目中
allprojects {
    repositories {
        mavenLocal()
        ...
    }
}

implementation '${YOUR_GROUP_ID}:${YOUR_ARTIFACT_ID}:${YOUR_VERSION}'


1
投票

假设您已经构建了 .aar,并将其发布到 Maven 存储库(artifactory、nexus,等等) - 例如,“implementation 'com.mycompany:library:1.0@aar'”。任何子依赖项都需要包含在服务器提供的 pom.xml 中,以便它们在您的应用程序中可用。

由于您使用了“implementation”关键字,这些依赖项被视为 .aar 私有的,并且不会在 pom.xml 中列出。所以它们不会在你的aar中可用,也不会被gradle自动导入到项目中。

如果将 api 关键字更改为“api”而不是实现,则这些依赖项将变为公共,并且应在生成的 pom.xml 中列出,因此应自动导入到项目中。

aar 的内部模块实际上也是如此,而不是通过外部系统引用(例如实现项目(':mylibrary'))。如果您需要 mylibrary 的依赖来运行项目,则它们需要是 api。

作为参考,您可能需要查看 Android Studio 依赖项配置文档

但是,如果您通过文件语句手动包含 arr(例如,实现文件('libs/my.aar')),那么您将无法获得自动依赖项管理,并且您将不得不通过在 build.gradle 文件之间复制和粘贴,手动将 aar 所需的库添加到主项目中。


0
投票

您可以尝试使用

fat-aar
来解决这个问题https://github.com/kezong/fat-aar-android


0
投票

2024 年解决方案:

对我来说,解决方法是将 gradle 中的

compileOnly files('libs/mylibrary.aar')
更改为
implementation files('libs/mylibrary.aar')
,错误就消失了。

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