非常棒的选题!
从 SSP 集成到 Gradle 构建:一个 Android SDK 开发者的踩坑全记录》这个主题非常典型,尤其适合 Android SDK 方向的技术博文或中高级开发者的分享文案。下面我给出一份完整的技术文章结构 + 实战细节说明,覆盖 SSP → AAR → Maven/Gradle 发布与兼容性调试 全流程,并在每一节穿插“坑点 + 解决方案”。


🧭 一、前言:为什么这一路这么坎

做 Android SDK 的人都知道:
从把一个 .jar 集成到 Demo 工程,到能优雅地通过 Gradle 引入你的 SDK,中间的坑堪比地狱副本。
而当项目中引入 SSP(Shared SDK Platform) 模块化架构后,坑的数量更是指数上升。

本文记录我在将 SSP 平台 SDK 模块迁移至 Gradle 构建体系中的完整踩坑过程,涵盖:

  • SDK 模块化设计 → Gradle 多模块构建;
  • AAR 打包与资源冲突;
  • Maven 发布与依赖解析;
  • Android Gradle Plugin(AGP)版本坑;
  • 以及最关键的:如何让 SSP 模块在 Gradle 中“既能跑、又能发”

⚙️ 二、背景:SSP 是什么,它为什么这么难搞

SSP(Shared SDK Platform)是一种 统一的 SDK 架构方案,常用于公司内部多个业务 SDK 的统一封装。
它通常包含:

  • 一组核心模块(如 ssp-core, ssp-utils, ssp-analytics);
  • 一套基础通信框架(跨 SDK 共享的网络层、配置中心、日志收集);
  • 多个业务侧 SDK 通过 compileOnlyapi 引用 SSP 核心模块。

📌 问题在于:
SSP 设计之初往往以“本地 module 依赖”为主,而当你要打包成单独 AAR 并发布到 Maven 仓库时:

  • 模块间依赖错综复杂;
  • 资源命名冲突;
  • Gradle Plugin 版本不兼容;
  • SSP 内部的构建脚本往往不适配外部环境。

🧩 三、迁移之路第一步:Gradle 多模块拆解

✅ 目标

将原本单体的 SSP SDK(包含数十个模块)逐步迁移到标准 Gradle 构建体系中。

⚠️ 坑点 1:模块互相引用 + api/implementation 混乱

原 SSP 工程里常见这种依赖:

dependencies {
    api project(':ssp-core')
    api project(':ssp-analytics')
}

但当这些模块要被打包为单独 AAR 时,Gradle 会提示:

“Cannot resolve project dependencies when publishing to Maven”

解决:

  • api project(':xxx') 改为 api 'com.company.ssp:xxx:1.0.0'
  • 统一在 settings.gradle 里用 includeBuildcomposite build 模式调试
    (这样在本地仍能源码依赖,发布时又能走 Maven)

🧱 四、打包 AAR:从 assembleRelease 到自定义 Task

⚠️ 坑点 2:资源文件冲突

多个 SSP 模块各自带有 /res/values/strings.xml/res/drawable/ic_logo.xml,结果在打包时出现:

Duplicate resources detected: res/values/strings.xml

解决:

  • 在 SSP 核心模块中统一 resPrefix,例如: android { resourcePrefix "ssp_" }
  • 对外暴露资源时,定义公共前缀(如 ssp_common_)避免冲突;
  • 对业务 SDK 的资源则使用 consumerProguardFiles 控制可见性。

⚠️ 坑点 3:R 文件合并失败

由于 SSP 模块使用了 android.enableAapt2=true(新 Gradle 默认开启),老版本 SSP 的 R.java 静态引用方式报错:

symbol not found for R.string.xxx

解决:

  • 不再直接引用 com.ssp.core.R.xxx
  • 使用 context.getResources().getIdentifier() 或 Resource Binding;
  • 或升级 AGP 版本 ≥ 7.0 并启用命名空间: android { namespace "com.ssp.core" }

📦 五、发布到 Maven:从 maven-publish 到自建仓库

⚠️ 坑点 4:Gradle Plugin 版本不兼容

SSP 工程中原用 com.github.dcendents.android-maven,在 Gradle 7+ 已弃用。

解决:使用官方 maven-publish 插件

publishing {
    publications {
        release(MavenPublication) {
            from components.release
            groupId = 'com.company.ssp'
            artifactId = 'ssp-core'
            version = '1.0.0'
        }
    }
}

⚠️ 坑点 5:AAR 无法携带依赖

默认 AAR 发布不会包含 transitive dependencies。

解决:
添加自定义 dependencies 块:

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)
    }
}


🧰 六、测试与验证:Demo 工程的噩梦调试

⚠️ 坑点 6:SSP 初始化失败(ClassNotFound)

AAR 被引用后运行时报:

java.lang.ClassNotFoundException: com.ssp.core.SSPManager

原因:AAR 被打包但 proguard 混淆掉核心类。

解决:

  • consumer-proguard-rules.pro 中添加: -keep class com.ssp.** { *; }
  • 在发布脚本中声明: consumerProguardFiles 'consumer-rules.pro'

🚀 七、最终架构与构建流程总结

.
├── ssp-core/              # 核心逻辑
├── ssp-analytics/         # 数据统计
├── ssp-utils/             # 工具模块
├── sdk-demo/              # 测试 Demo
├── build.gradle           # 顶层构建
└── settings.gradle        # includeBuild 管理

发布流程:

  1. 本地调试:./gradlew :ssp-core:assembleRelease
  2. 校验依赖:./gradlew dependencies
  3. 发布 Maven:./gradlew publishReleasePublicationToMavenRepository
  4. Demo 引用测试: implementation 'com.company.ssp:ssp-core:1.0.0'

🧠 八、踩坑后的总结与经验沉淀

问题现象根因解决方案
AAR 资源冲突strings.xml 重复未设置 resPrefix统一命名 + resourcePrefix
ClassNotFoundSSPManager 找不到混淆掉类添加 consumerProguard
构建失败Gradle Plugin 版本不兼容plugin 弃用用官方 maven-publish
依赖丢失SDK 引入后功能不全未声明 transitive depsPOM 手动注入依赖
Demo 无法运行SSP 模块命名空间冲突namespace 未设Gradle 7+ 明确命名空间

📚 九、参考资料与出站链接