Android多SDK合并为单个JAR包的完整指南

痛点

  • 多 SDK 分散:每个功能模块单独提供 JAR,用户需要逐一集成和管理
  • 调用复杂:不同模块间存在依赖和包名冲突,用户在项目中使用不方便
  • 升级维护困难:每次更新都要同步多个 JAR,容易出错

一、核心原理

1.1 最推荐的方案:源码合并 + 下层库作为"源码目录"加入

多 SDK 合并时,最终有效的构建环境只有顶层 SDK,因此最稳定的方式是:

diff 复制代码
源码合并(sourceSets)  
+ 移除模块依赖  
+ 将下层 SDK 作为源码目录引入(而不是 module)

Android Studio 会把下层 SDK 当成普通源码,自然不会爆红,也不会再触发 module 依赖的复杂机制。


1.2 为什么不能继续使用 module 依赖?

java 复制代码
dependencies {
    api project(':sdk-core-lib')  // ❌ 不推荐
}

问题:

  • AAR/JAR 输出不一定包含所有依赖模块代码
  • 需要额外处理传递依赖
  • fat-aar 插件在 Gradle 8+ 兼容性差
  • 模块之间 BuildConfig、Manifest、资源合并容易冲突
  • 最重要:module 依赖让下层 SDK 的 build.gradle 继续生效(会导致混淆等配置难以统一管理)

1.3 最关键的优化:用 sourceSets 把下层 SDK 当成"源码目录"

比直接复制代码更干净 ------ 下层 SDK 不再是 module,只是一个源码目录。

css 复制代码
android {
    sourceSets {
        main {
            java.srcDirs += ['../SDK_Core/src/main/java']
            java.srcDirs += ['../SDK_Base/src/main/java']
            res.srcDirs  += ['../SDK_Core/src/main/res']
            res.srcDirs  += ['../SDK_Base/src/main/res']
        }
    }
}

同时从 settings.gradle 中删除:

php 复制代码
include ':SDK_Core'
include ':SDK_Base'

优点:

  • Android Studio 能识别源码,不再爆红(你遇到的问题的核心原因)
  • 不再有 Gradle module 带来的依赖逻辑
  • 完全由顶层 SDK 的 build.gradle 决定最终产物
  • 源码共享更干净,不需要复制

缺点:

  • 不再能享受 Gradle dependency graph(因为不是 module)
  • 无法单独编译下层 SDK(但通用 SDK 开发通常不需要)

二、适用架构与合并策略

以典型结构为例:

复制代码
SDK_Standard(对客户的最终输出)
 ├── SDK_Core
 │     └── SDK_Base

所有差异化功能由顶层 SDK(Standard / Custom_A / Custom_B)决定。


三、核心规则(⭐ 极重要)

规则 1:所有下层 SDK 必须作为源码目录存在

❌ 不要是 module

❌ 不要使用依赖

✔ 使用 sourceSets 直接引用源码目录(不会爆红)


规则 2:只有顶层 SDK 的 build.gradle 生效

下层的 build.gradle 完全无效(因为不再是 module)。

失效内容:

全部迁移到顶层。


规则 3:资源文件自动合并,但必须避免冲突

建议命名规范:

SDK 前缀
SDK_Base base_
SDK_Core core_
SDK_Standard standard_

规则 4:避免包名冲突

下层 SDK 必须独立包目录,例如:

csharp 复制代码
com.company.base.**
com.company.core.**
com.company.sdk.standard.**

四、完整实现步骤


4.1 顶层 build.gradle(唯一有效)

arduino 复制代码
android {
    namespace 'com.company.sdk.standard'
    compileSdk 34

    defaultConfig {
        minSdk 21
        targetSdk 34
    }

    sourceSets {
        main {
            // 源码合并
            java.srcDir '../SDK_Core/src/main/java'
            java.srcDir '../SDK_Base/src/main/java'

            // 资源合并(如需要)
            res.srcDir '../SDK_Core/src/main/res'
            res.srcDir '../SDK_Base/src/main/res'
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                         'proguard-rules.pro'
        }
    }
}

4.2 迁移所有依赖到顶层

arduino 复制代码
dependencies {
    // 来自 Core
    implementation 'androidx.core:core-ktx:1.12.0'

    // 来自 Base
    implementation 'com.google.code.gson:gson:2.10.1'
}

4.3 BuildConfig 失效问题(非常常见)

下层 SDK 不再是 module,所以不会生成 BuildConfig。

解决方式 A(推荐)

修改引用路径:

arduino 复制代码
// from
import com.company.sdk.core.BuildConfig;

// to
import com.company.sdk.standard.BuildConfig;

解决方式 B(无需改源码)

手动创建对应 BuildConfig:

css 复制代码
SDK_Standard/src/main/java/com/company/sdk/core/BuildConfig.java

4.4 混淆规则合并(放在顶层)

csharp 复制代码
# Base
-keep class com.company.base.** { *; }

# Core
-keep class com.company.core.** { *; }

# 顶层对外接口
-keep public class com.company.sdk.MTTagBleManager { *; }

4.5 最终目录结构(重要)

bash 复制代码
SDK_Standard/
 ├── build.gradle(唯一有效)
 ├── proguard-rules.pro
 └── src/main/java/
       ├── com/company/sdk/standard/...
       ├── com/company/core/...     ← via sourceSets
       └── com/company/base/...     ← via sourceSets

五、为什么之前代码会爆红?

因为:

  • 你删掉 settings.gradle 里的 include
  • 但没有把 SDK_Core / SDK_Base 作为 sourceSets 手动加入
  • Android Studio 不知道这些目录是源码目录
  • 所以爆红(找不到类)

只要加上这个:

核心痛点

  • 多 SDK 分散:每个功能模块单独提供 JAR,用户需要逐一集成和管理
  • 调用复杂:不同模块间存在依赖和包名冲突,用户在项目中使用不方便
  • 升级维护困难:每次更新都要同步多个 JAR,容易出错
css 复制代码
android {
    sourceSets {
        main {
            java.srcDirs += ['../SDK_Core/src/main/java']
        }
    }
}

即时恢复正常。

这是你目前问题的根源,并且已经彻底解决。


六、总结

能力 为什么必须使用源码目录方式
不爆红 Android Studio 能识别源码
打包稳定 所有代码由顶层统一构建
混淆统一 避免多 module 冲突
完全控制 不再受 module 的 build.gradle 干扰
干净 不需要复制源码

最终输出:

  • 单 AAR / 单 JAR
  • 完整包含 Base + Core + Standard 的全部代码
  • 无依赖问题
  • 完整兼容 Gradle 8+
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui