如何在Android .aar项目中修复'java.lang.NoClassDefFoundError'

时间:2019-07-11 12:46:20

标签: android retrofit2 okhttp3 aar

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

  

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

我没有在我的.aar项目中混淆或启用过支持。

下面是我的.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'

2 个答案:

答案 0 :(得分:5)

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

  1. 通过使用以下命令将此aar作为模块导入到您的示例项目中 implementation project(':mylibrary')
  2. 通过将aar上传到Maven存储库(人工工具,maven本地,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)
                    }
                }
            }
        }
    }
}

运行assemblepublishToMavenLocal gradle任务。您会看到类似以下内容: enter image description here

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

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

答案 1 :(得分:0)

让我们假设您已经构建了.aar,并将其发布到了一个maven仓库(人工工厂,联系,您所拥有的仓库)-例如,“实施'com.mycompany:library:1.0@aar'”。服务器提供的pom.xml中必须包含所有子依赖项,以使其在您的应用程序中可用。

由于使用了“ implementation”关键字,因此那些依赖项被认为是.aar私有的,因此不会在pom.xml中列出。因此它们将不会在您的助手中使用,也不会通过gradle自动导入到项目中。

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

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

作为参考,您可能想看看Android Studio Dependency Configurations Documentation

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