痛点
- 多 SDK 分散:每个功能模块单独提供 JAR,用户需要逐一集成和管理
- 调用复杂:不同模块间存在依赖和包名冲突,用户在项目中使用不方便
- 升级维护困难:每次更新都要同步多个 JAR,容易出错
一、核心原理
1.1 最推荐的方案:源码合并 + 下层库作为“源码目录”加入
多 SDK 合并时,最终有效的构建环境只有顶层 SDK,因此最稳定的方式是:
1源码合并(sourceSets) 2+ 移除模块依赖 3+ 将下层 SDK 作为源码目录引入(而不是 module) 4
Android Studio 会把下层 SDK 当成普通源码,自然不会爆红,也不会再触发 module 依赖的复杂机制。
1.2 为什么不能继续使用 module 依赖?
1dependencies { 2 api project(':sdk-core-lib') // ❌ 不推荐 3} 4
问题:
- AAR/JAR 输出不一定包含所有依赖模块代码
- 需要额外处理传递依赖
- fat-aar 插件在 Gradle 8+ 兼容性差
- 模块之间 BuildConfig、Manifest、资源合并容易冲突
- 最重要:module 依赖让下层 SDK 的 build.gradle 继续生效(会导致混淆等配置难以统一管理)
1.3 最关键的优化:用 sourceSets 把下层 SDK 当成“源码目录”
比直接复制代码更干净 —— 下层 SDK 不再是 module,只是一个源码目录。
1android { 2 sourceSets { 3 main { 4 java.srcDirs += ['../SDK_Core/src/main/java'] 5 java.srcDirs += ['../SDK_Base/src/main/java'] 6 res.srcDirs += ['../SDK_Core/src/main/res'] 7 res.srcDirs += ['../SDK_Base/src/main/res'] 8 } 9 } 10} 11
同时从 settings.gradle 中删除:
1include ':SDK_Core' 2include ':SDK_Base' 3
优点:
- Android Studio 能识别源码,不再爆红(你遇到的问题的核心原因)
- 不再有 Gradle module 带来的依赖逻辑
- 完全由顶层 SDK 的 build.gradle 决定最终产物
- 源码共享更干净,不需要复制
缺点:
- 不再能享受 Gradle dependency graph(因为不是 module)
- 无法单独编译下层 SDK(但通用 SDK 开发通常不需要)
二、适用架构与合并策略
以典型结构为例:
1SDK_Standard(对客户的最终输出) 2 ├── SDK_Core 3 │ └── SDK_Base 4
所有差异化功能由顶层 SDK(Standard / Custom_A / Custom_B)决定。
三、核心规则(⭐ 极重要)
规则 1:所有下层 SDK 必须作为源码目录存在
❌ 不要是 module
❌ 不要使用依赖
✔ 使用 sourceSets 直接引用源码目录(不会爆红)
规则 2:只有顶层 SDK 的 build.gradle 生效
下层的 build.gradle 完全无效(因为不再是 module)。
失效内容:
- dependencies
- buildConfigField
- proguard-rules.pro
- manifestPlaceholders
全部迁移到顶层。
规则 3:资源文件自动合并,但必须避免冲突
建议命名规范:
| SDK | 前缀 |
|---|---|
| SDK_Base | base_ |
| SDK_Core | core_ |
| SDK_Standard | standard_ |
规则 4:避免包名冲突
下层 SDK 必须独立包目录,例如:
1com.company.base.** 2com.company.core.** 3com.company.sdk.standard.** 4
四、完整实现步骤
4.1 顶层 build.gradle(唯一有效)
1android { 2 namespace 'com.company.sdk.standard' 3 compileSdk 34 4 5 defaultConfig { 6 minSdk 21 7 targetSdk 34 8 } 9 10 sourceSets { 11 main { 12 // 源码合并 13 java.srcDir '../SDK_Core/src/main/java' 14 java.srcDir '../SDK_Base/src/main/java' 15 16 // 资源合并(如需要) 17 res.srcDir '../SDK_Core/src/main/res' 18 res.srcDir '../SDK_Base/src/main/res' 19 } 20 } 21 22 buildTypes { 23 release { 24 minifyEnabled true 25 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 26 'proguard-rules.pro' 27 } 28 } 29} 30
4.2 迁移所有依赖到顶层
1dependencies { 2 // 来自 Core 3 implementation 'androidx.core:core-ktx:1.12.0' 4 5 // 来自 Base 6 implementation 'com.google.code.gson:gson:2.10.1' 7} 8
4.3 BuildConfig 失效问题(非常常见)
下层 SDK 不再是 module,所以不会生成 BuildConfig。
解决方式 A(推荐)
修改引用路径:
1// from 2import com.company.sdk.core.BuildConfig; 3 4// to 5import com.company.sdk.standard.BuildConfig; 6
解决方式 B(无需改源码)
手动创建对应 BuildConfig:
1SDK_Standard/src/main/java/com/company/sdk/core/BuildConfig.java 2
4.4 混淆规则合并(放在顶层)
1# Base 2-keep class com.company.base.** { *; } 3 4# Core 5-keep class com.company.core.** { *; } 6 7# 顶层对外接口 8-keep public class com.company.sdk.MTTagBleManager { *; } 9
4.5 最终目录结构(重要)
1SDK_Standard/ 2 ├── build.gradle(唯一有效) 3 ├── proguard-rules.pro 4 └── src/main/java/ 5 ├── com/company/sdk/standard/... 6 ├── com/company/core/... ← via sourceSets 7 └── com/company/base/... ← via sourceSets 8
五、为什么之前代码会爆红?
因为:
- 你删掉 settings.gradle 里的 include
- 但没有把 SDK_Core / SDK_Base 作为 sourceSets 手动加入
- Android Studio 不知道这些目录是源码目录
- 所以爆红(找不到类)
只要加上这个:
核心痛点
- 多 SDK 分散:每个功能模块单独提供 JAR,用户需要逐一集成和管理
- 调用复杂:不同模块间存在依赖和包名冲突,用户在项目中使用不方便
- 升级维护困难:每次更新都要同步多个 JAR,容易出错
1android { 2 sourceSets { 3 main { 4 java.srcDirs += ['../SDK_Core/src/main/java'] 5 } 6 } 7} 8
即时恢复正常。
这是你目前问题的根源,并且已经彻底解决。
六、总结
| 能力 | 为什么必须使用源码目录方式 |
|---|---|
| 不爆红 | Android Studio 能识别源码 |
| 打包稳定 | 所有代码由顶层统一构建 |
| 混淆统一 | 避免多 module 冲突 |
| 完全控制 | 不再受 module 的 build.gradle 干扰 |
| 干净 | 不需要复制源码 |
最终输出:
- 单 AAR / 单 JAR
- 完整包含 Base + Core + Standard 的全部代码
- 无依赖问题
- 完整兼容 Gradle 8+
《Android多SDK合并为单个JAR包的完整指南》 是转载文章,点击查看原文。