开发Android库依赖发布问题:引用后遇NoClassDefFoundError
我正在开发一个Android库,在项目模块中声明了若干依赖并发布到本地Maven仓库,模块的build.gradle.kts依赖配置如下:
dependencies { // Retrofit implementation(libs.retrofit) implementation(libs.retrofit.gson) implementation(libs.okhttp) implementation(libs.okhttp.logging) // room implementation(libs.room.runtime) implementation(libs.room.ktx) ksp(libs.room.compiler) testImplementation(libs.room.testing) // Work Manager implementation(libs.work.runtime.ktx) // Play services implementation(libs.play.services.location) // DI implementation(libs.koin.android) }
发布配置如下:
publishing { publications { create<MavenPublication>("release") { artifact("$buildDir/outputs/aar/${project.name}-release.aar") groupId = "com.mylibrary.android" artifactId = "core" version = project.extra["baseVersionName"] as String } } repositories { maven { url = uri("${project.buildDir}/repo") } } }
执行./gradlew assembleRelease和./gradlew publish后成功生成AAR文件,但在示例应用中用implementation("com.mylibrary.android:core:0.3.1")引用该SDK时,出现java.lang.NoClassDefFoundError: Failed resolution of:错误。我不希望示例应用单独声明这些依赖,尝试将implementation替换为api但无效,也了解到fat-aar方案,不确定是否正确,想知道处理库依赖的正确方式,以及是否应将依赖随库一同发布。
1. 修复发布配置,自动生成依赖元数据
你当前的发布配置直接指定本地AAR文件作为artifact,这种方式不会生成包含依赖信息的pom.xml文件,导致示例应用无法通过依赖传递获取库的依赖。正确的做法是让Gradle自动处理组件发布,修改publishing配置如下:
publishing { publications { create<MavenPublication>("release") { // 替换直接指定aar的方式,使用组件发布 from(components["release"]) groupId = "com.mylibrary.android" artifactId = "core" version = project.extra["baseVersionName"] as String } } repositories { maven { url = uri("${project.buildDir}/repo") } } }
这样Gradle会自动生成包含依赖关系的pom.xml,示例应用引用时会自动拉取所需的传递依赖。
2. 正确区分implementation和api的使用
api:用于库对外暴露的依赖,即如果你的库的公共API中直接使用了某个依赖的类型(比如方法参数返回Retrofit的Call对象),就用api声明,这样依赖会传递给示例应用。implementation:用于库内部仅自己使用的依赖,不会传递给上层应用。
你之前替换implementation为api无效,就是因为发布配置没生成正确的pom文件,现在修复发布配置后,这个区分就能生效。
3. 关于fat-aar方案
除非你的依赖是无法通过Maven仓库访问的私有本地库,否则不推荐使用fat-aar。fat-aar会把所有依赖打包进你的库的AAR中,带来以下问题:
- 增大库的体积,导致示例应用安装包变大。
- 容易引发依赖冲突(比如示例应用本身也依赖了相同库的不同版本)。
- 破坏Maven的依赖传递机制,不符合标准的库发布规范。
4. 验证发布结果
重新执行./gradlew publish后,查看本地Maven仓库中com/mylibrary/android/core/0.3.1目录下的core-0.3.1.pom文件,确认其中包含了你的库的依赖声明。此时示例应用重新同步Gradle后,就能自动获取所需依赖,不会再出现NoClassDefFoundError。
内容的提问来源于stack exchange,提问作者Ziv Kesten

