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

如何修复';java.lang.NoClassDefFoundError';在Android.aar项目中,android,retrofit2,okhttp3,aar,Android,Retrofit2,Okhttp3,Aar,我构建了一个android.aar库,我正在尝试将其与其中一个项目集成。当应用程序尝试打开.aar库的初始屏幕时,我使用改型进行API调用。我得到下面的例外 java.lang.NoClassDefFoundError:解析失败 of:Lokhttp3/Okhttp客户$Builder 我没有在.aar项目中混淆或启用pro guard 下面是我的.aar渐变依赖项 implementation fileTree(dir: 'libs', include: ['*.jar']) implemen

我构建了一个android
.aar
库,我正在尝试将其与其中一个项目集成。当应用程序尝试打开
.aar
库的初始屏幕时,我使用改型进行API调用。我得到下面的例外

java.lang.NoClassDefFoundError:解析失败 of:Lokhttp3/Okhttp客户$Builder

我没有在
.aar
项目中混淆或启用pro guard

下面是我的
.aar
渐变依赖项

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'

让我们假设您已经构建了您的.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

作为参考,您可能想看一下


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

OK,这是一个普遍的问题。在其他项目中使用android库(aar)有几种方法。例如:

  • 通过使用将此aar作为模块导入示例项目
    实施项目(':mylibrary')
  • 通过将aar上传到maven存储库(artifactory、maven local、Jitpack等)
  • 注意这一点:

  • 如果您使用上面的数字1,那么您还必须 将(改造、okhttp3等)添加到您的示例项目中,并使用相同的 版本,因为默认情况下aar不包括子级 依赖关系。这就是为什么你会得到这个例外 “java.lang.NoClassDefFoundError:解析失败: Lokhttp3/OkHttpClient$Builder'”
  • 如果您使用的是上面的数字2,那么您必须确保pom.xml文件包含您的子依赖项,因为服务器需要下载这些子依赖项,并在示例项目中提供它们
  • 我推荐什么?

    我建议开发人员使用
    MavenLocal()
    ,它在将aar发布到公共存储库(如Jitpack)或任何您想要的东西之前复制真实场景

    我该怎么做?

  • 库模块的内部build.gradle
  • 应用插件:“maven发布”

    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)
                        }
                    }
                }
            }
        }
    }
    
    运行
    assembly
    publishtoavenlocal
    gradle任务。你会看到这样的情况:

  • 在您的示例项目中

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

    是否启用了即时运行?在android M下运行你的应用程序?你是如何在使用它的项目中引用aar的?@Mark implementation project(path:“:LibraryName”)我是如何引用aar@RajasekaranM我已禁用instant run并在android MSN中运行应用程序,直到问题存在?感谢您的建议和帮助@Mark。我还没有将我的.aar发布到maven存储库。这是一个本地模块,我试图使用类似于“api项目(“:MyLibrary”)的api导入库,但不起作用。不,在MyLibrary模块中,您需要将依赖项从实现更改为api,例如okhttp、改型等。然后它们将是“公共”的,并可供您的父项目使用。谢谢,Mark我已将我的库模块依赖项从模块更改为api,并在项目中重新导入了库,但我有相同的问题java.lang.NoClassDefFoundError:未能解决:Lokhttp3/OkHttpClient$Builder'如果您有“api”com.squareup.okhttp3:okhttp:3.12.0',您仍然会收到此消息。。。您是否尝试过关闭proguard(可能是您缺少proguard规则,而类正在被剥离)。是的,我尝试过关闭proguard,甚至尝试过添加proguard规则,但仍然有相同的错误消息。
    allprojects {
        repositories {
            mavenLocal()
            ...
        }
    }