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+
相关推荐
事圆则缓25 分钟前
HTTP 请求是怎么走的:从 Android 页面到服务端响应
android·网络协议·http
美狐美颜SDK开放平台2 小时前
直播APP平台搭建需要哪些技术?视频美颜SDK只是其中一环
android·ios·音视频·直播美颜sdk·视频美颜sdk
AIsoft_86893 小时前
传统记录方式为什么越来越难满足需求?
android·iphone
小π军3 小时前
安卓、iOS、鸿蒙三端的理解
android·ios·harmonyos
BD_Marathon4 小时前
ChatPromptTemplate的高级特性
android·java·javascript
夜晚回家4 小时前
Python 变量入门详解 | 用 BMI 案例串起赋值、乘方与取整
android·python
程序猿追4 小时前
立方体转到九十度:用 kotlin-math 核对鸿蒙上的两种旋转
android·开发语言·kotlin
半调子的社畜4 小时前
记账 App 我装了删、删了装,最后自己写了一个:本地语音识别 + R8 踩坑复盘
android·ai编程
hunterandroid5 小时前
Android 运行时权限实战:从声明权限到拒绝后的可用降级
android
a5986525 小时前
docker-android 6080 端口访问失败?
android·docker·容器·云手机