SDK Development
SKILL.md
SDK Development (SDK/Library 开发)
Instructions
- 确认需求属于 SDK/Library 开发(非 App 开发)
- 先填写 Required Inputs,冻结发布坐标与兼容范围
- 依照下方章节顺序套用
- 一次只处理一个面向(API 设计、发布、文档)
- 完成后对照 Quick Checklist
When to Use
- 开发供第三方使用的 Android SDK/Library
- 需要发布 AAR/KLib 到 Maven Central 或私有仓库
- 需要设计稳定的 Public API 与版本策略
Example Prompts
- "请依照 API Design 章节设计 SDK 的公开接口"
- "帮我配置 Maven Central 发布流程"
- "请用 Binary Compatibility 章节检查 API 变更"
- "帮我创建 SDK 的 Sample App"
Workflow
- 先确认 Required Inputs(group/artifact、最低支持、版本策略)
- 设计 Public API 与模块结构,并冻结 API surface
- 配置 Consumer Proguard 与依赖传递策略
- 设置发布流程(Maven Central / 私有仓库)与签章密钥
- 创建文档与 Sample App,补齐迁移与升级说明
- 运行 Release Gate 指令,再用 Quick Checklist 验收
Practical Notes (2026)
- Public API 必须最小化,只暴露必要接口
- 二进制兼容性检查纳入 CI Gate
- SDK 依赖尽量用 compileOnly 避免传递冲突
- Sample App 是最好的 API 验证工具
- 版本号、groupId、artifactId 只保留单一来源(
gradle.properties或 version catalog) - 发布流程必须支持 dry-run,先验证再正式发布
- 所有发布凭证只允许来自 CI secret,不进入仓库
Minimal Template
目标:
SDK 名称:
groupId/artifactId:
版本策略(SemVer):
最低 Android/JDK:
目标用户:
Public API 范围:
发布目标:
验收: Quick Checklist
Required Inputs (执行前输入)
groupId / artifactId / version(单一来源,禁止分散在多个脚本)minSdk / compileSdk / targetSdk / jdkVersionPublic API 边界(哪些 package 对外、哪些仅 internal)发布渠道(Maven Central / 私有仓库)签章策略(GPG key 来源、轮换方式、CI secret 名称)兼容策略(BCV/metalava 选型、deprecation 时间表)
Deliverables (完成后交付物)
sdk-api+sdk-core(可选sdk-network/sdk-storage)consumer-rules.pro与发布 AAR 一起分发publishworkflow(含签章、发布、失败回滚说明)apiCheckworkflow(PR 阶段执行)Dokka文档与CHANGELOG.mdsample-app可运行并覆盖核心/错误/进阶场景
Release Gate (发布前硬门槛)
# 1) 基础质量
./gradlew lint test assemble
# 2) API 兼容性
./gradlew apiCheck
# 3) 文档产物
./gradlew dokkaHtml
# 4) 发布演练(不触发正式 release)
./gradlew publishToMavenLocal
只有上述命令全部通过,才允许执行正式发布任务。
API Design & Visibility Control
最小化 Public API
// ❌ 错误:暴露过多实现细节
class MySDK {
val internalCache: MutableMap<String, Any> = mutableMapOf() // 不应该 public
fun processInternal(data: String) { } // 不应该 public
}
// ✅ 正确:只暴露必要接口
interface MySDK {
fun initialize(context: Context, config: Config) { }
fun performAction(input: String): Result<Output>
}
Visibility Modifiers 策略
// Public API — 供外部使用
public class MySDK { }
public interface Callback { }
// Internal — 跨模块共享但不对外
internal class NetworkClient { }
internal object ConfigValidator { }
// Private — 模块内部
private class CacheManager { }
Sealed Interface 限制实现
// 防止外部实现接口
sealed interface Result<out T> {
data class Success<T>(val data: T) : Result<T>
data class Error(val exception: Exception) : Result<Nothing>
}
// 用户只能消费,不能创建新的 Result 子类
Module Structure
多模块分层
my-sdk/
├── sdk-api/ # Public API 定义(纯接口)
├── sdk-core/ # 核心实现
├── sdk-network/ # 网络模块(可选依赖)
├── sdk-storage/ # 存储模块(可选依赖)
└── sample-app/ # 示例应用
sdk-api Module
// sdk-api/build.gradle.kts — 纯接口,无依赖
plugins {
id("com.android.library")
kotlin("android")
}
dependencies {
// 无外部依赖,只有 Kotlin stdlib
}
// sdk-api/src/main/kotlin/MySDK.kt
interface MySDK {
fun initialize(context: Context, config: Config)
fun performAction(input: String): Result<Output>
}
data class Config(
val apiKey: String,
val enableLogging: Boolean = false
)
sdk-core Module
// sdk-core/build.gradle.kts
plugins {
id("com.android.library")
kotlin("android")
}
dependencies {
api(project(":sdk-api")) // 暴露 API 定义
implementation(libs.okhttp) // 不传递给消费者
implementation(libs.kotlinx.coroutines.android)
}
// sdk-core/src/main/kotlin/MySDKImpl.kt
internal class MySDKImpl(
private val context: Context,
private val config: Config
) : MySDK {
override fun initialize(context: Context, config: Config) {
// 初始化逻辑
}
override fun performAction(input: String): Result<Output> {
// 实现逻辑
return Result.Success(Output(input))
}
}
// Factory 作为唯一入口
object MySDKFactory {
fun create(context: Context, config: Config): MySDK {
return MySDKImpl(context, config)
}
}
Consumer Proguard Rules
创建 consumer-rules.pro
# sdk-core/consumer-rules.pro — 自动应用到消费者的 Proguard 规则
# 保留 Public API
-keep public class com.example.sdk.MySDK { *; }
-keep public class com.example.sdk.Config { *; }
-keep public class com.example.sdk.Result { *; }
# 保留 Kotlin metadata(用于反射)
-keep class kotlin.Metadata { *; }
# 保留 Coroutines
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
# 如果使用 Retrofit
-keepattributes Signature, InnerClasses, EnclosingMethod
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
-keepclassmembers,allowsetter,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
在 build.gradle.kts 中引用
android {
defaultConfig {
consumerProguardFiles("consumer-rules.pro")
}
}
Dependency Strategy
api vs implementation vs compileOnly
dependencies {
// api — 暴露给消费者(慎用)
api(project(":sdk-api")) // 消费者需要直接使用 API 接口
api(libs.kotlinx.coroutines.core) // 返回值中有 Flow/suspend
// implementation — 不传递(推荐)
implementation(libs.okhttp) // 内部使用,不暴露
implementation(libs.gson)
// compileOnly — 编译时可用,运行时由消费者提供(避免冲突)
compileOnly(libs.androidx.annotation) // 消费者通常已有
}
依赖冲突处理
// 如果 SDK 依赖的库与消费者冲突,用 compileOnly + 文档说明
dependencies {
compileOnly(libs.okhttp) {
because("Consumers should provide their own OkHttp version")
}
}
<!-- README.md -->
## Dependencies
This SDK requires the following dependencies in your app:
```gradle
implementation("com.squareup.okhttp3:okhttp:<project-verified-version>")
```
Maven Central Publishing
配置 maven-publish Plugin
// sdk-core/build.gradle.kts
plugins {
id("com.android.library")
kotlin("android")
id("maven-publish")
id("signing")
}
android {
publishing {
singleVariant("release") {
withSourcesJar()
withJavadocJar()
}
}
}
publishing {
publications {
create<MavenPublication>("release") {
from(components["release"])
groupId = "com.example"
artifactId = "my-sdk"
version = "1.0.0"
pom {
name.set("My SDK")
description.set("A powerful Android SDK")
url.set("https://github.com/example/my-sdk")
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
developers {
developer {
id.set("example")
name.set("Example Developer")
email.set("dev@example.com")
}
}
scm {
connection.set("scm:git:git://github.com/example/my-sdk.git")
developerConnection.set("scm:git:ssh://github.com/example/my-sdk.git")
url.set("https://github.com/example/my-sdk")
}
}
}
}
repositories {
maven {
name = "sonatype"
url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = System.getenv("OSSRH_USERNAME")
password = System.getenv("OSSRH_PASSWORD")
}
}
}
}
signing {
sign(publishing.publications["release"])
}
生产建议:发布坐标单一来源
// gradle.properties (root)
GROUP=com.example
ARTIFACT_ID=my-sdk
VERSION_NAME=1.0.0
// sdk-core/build.gradle.kts
group = providers.gradleProperty("GROUP").get()
version = providers.gradleProperty("VERSION_NAME").get()
publishing {
publications {
create<MavenPublication>("release") {
artifactId = providers.gradleProperty("ARTIFACT_ID").get()
}
}
}
GitHub Actions 发布流程
# .github/workflows/publish.yml
name: Publish to Maven Central
on:
release:
types: [created]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Decode GPG Key
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 -d > private.gpg
gpg --import --batch private.gpg
- name: Publish to Maven Central
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
run: ./gradlew apiCheck dokkaHtml publish
- name: Clean GPG Key
if: always()
run: rm -f private.gpg
Binary Compatibility Validation
Binary Compatibility Validator (BCV)
// build.gradle.kts (root)
plugins {
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "<project-verified-version>"
}
apiValidation {
ignoredProjects.addAll(listOf("sample-app"))
nonPublicMarkers.add("com.example.sdk.InternalApi")
}
# 生成 API dump
./gradlew apiDump
# 检查 API 变更
./gradlew apiCheck
# sdk-api/api/sdk-api.api — 自动生成的 API 签名
public final class com/example/sdk/MySDK {
public fun initialize(Landroid/content/Context;Lcom/example/sdk/Config;)V
public fun performAction(Ljava/lang/String;)Lcom/example/sdk/Result;
}
Metalava (Android 官方)
// build.gradle.kts
plugins {
id("me.tylerbwong.gradle.metalava") version "<project-verified-version>"
}
metalava {
filename.set("api/current.txt")
reportLintsAsErrors.set(true)
}
CI Gate 集成
# .github/workflows/api-check.yml
name: API Compatibility Check
on:
pull_request:
branches: [main]
jobs:
api-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check API Compatibility
run: ./gradlew apiCheck
- name: Fail on Breaking Changes
if: failure()
run: |
echo "API breaking changes detected!"
echo "Run './gradlew apiDump' to update API signatures"
exit 1
Versioning & Deprecation Strategy
Semantic Versioning
MAJOR.MINOR.PATCH
MAJOR: 不兼容的 API 变更
MINOR: 向后兼容的新功能
PATCH: 向后兼容的 Bug 修复
Deprecation 流程
// 1. 标记 @Deprecated,提供替代方案
@Deprecated(
message = "Use performActionAsync instead",
replaceWith = ReplaceWith("performActionAsync(input)"),
level = DeprecationLevel.WARNING
)
fun performAction(input: String): Result<Output>
// 2. 提供新 API
suspend fun performActionAsync(input: String): Result<Output>
Deprecation 时间表
| 版本 | 动作 |
|---|---|
| 1.0.0 | 发布 API |
| 1.1.0 | 标记 @Deprecated (WARNING) |
| 1.2.0 | 升级为 ERROR |
| 2.0.0 | 移除 API |
CHANGELOG.md
# Changelog
## [1.2.0] - 2026-02-15
### Added
- New `performActionAsync` API with coroutine support
### Deprecated
- `performAction` is now ERROR level, will be removed in 2.0.0
### Fixed
- Memory leak in NetworkClient
## [1.1.0] - 2026-01-10
### Added
- Support for custom timeout configuration
### Deprecated
- `performAction` (use `performActionAsync` instead)
Dokka Documentation
配置 Dokka Plugin
// build.gradle.kts
plugins {
id("org.jetbrains.dokka") version "<project-verified-version>"
}
tasks.dokkaHtml.configure {
outputDirectory.set(buildDir.resolve("dokka"))
dokkaSourceSets {
named("main") {
moduleName.set("My SDK")
includes.from("Module.md")
sourceLink {
localDirectory.set(file("src/main/kotlin"))
remoteUrl.set(URL("https://github.com/example/my-sdk/tree/main/src/main/kotlin"))
remoteLineSuffix.set("#L")
}
}
}
}
KDoc 注释规范
/**
* SDK 主入口,负责初始化与核心操作。
*
* ## 使用示例
* ```kotlin
* val sdk = MySDKFactory.create(context, Config(apiKey = "xxx"))
* sdk.initialize(context, config)
* val result = sdk.performAction("input")
* ```
*
* @property context Android Context
* @property config SDK 配置
* @see Config
* @since 1.0.0
*/
interface MySDK {
/**
* 初始化 SDK。
*
* 必须在使用其他 API 前调用。
*
* @param context Android Application Context
* @param config SDK 配置对象
* @throws IllegalStateException 如果已初始化
*/
fun initialize(context: Context, config: Config)
/**
* 执行核心操作。
*
* @param input 输入字符串
* @return [Result.Success] 包含 [Output],或 [Result.Error] 包含异常
* @sample com.example.sdk.samples.performActionSample
*/
fun performAction(input: String): Result<Output>
}
生成文档
# 生成 HTML 文档
./gradlew dokkaHtml
# 生成 Javadoc JAR(用于 Maven Central)
./gradlew dokkaJavadocJar
Sample App Design
Sample App 模块结构
sample-app/
├── src/main/
│ ├── kotlin/
│ │ └── com/example/sample/
│ │ ├── MainActivity.kt
│ │ ├── BasicUsageFragment.kt
│ │ ├── AdvancedUsageFragment.kt
│ │ └── ErrorHandlingFragment.kt
│ └── res/
└── build.gradle.kts
build.gradle.kts
plugins {
id("com.android.application")
kotlin("android")
}
dependencies {
// 使用本地 SDK 模块
implementation(project(":sdk-core"))
// 或使用已发布版本
// implementation("com.example:my-sdk:<project-verified-version>")
}
示例代码组织
// BasicUsageFragment.kt — 基础用法
class BasicUsageFragment : Fragment() {
private lateinit var sdk: MySDK
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 1. 创建 SDK 实例
sdk = MySDKFactory.create(
requireContext(),
Config(apiKey = "demo_key")
)
// 2. 初始化
sdk.initialize(requireContext(), Config(apiKey = "demo_key"))
// 3. 执行操作
lifecycleScope.launch {
when (val result = sdk.performAction("test")) {
is Result.Success -> showSuccess(result.data)
is Result.Error -> showError(result.exception)
}
}
}
}
// AdvancedUsageFragment.kt — 进阶用法
class AdvancedUsageFragment : Fragment() {
private val sdk by lazy {
MySDKFactory.create(
requireContext(),
Config(
apiKey = "demo_key",
enableLogging = true
)
)
}
// 展示自定义配置、错误处理、并发操作等
}
README.md 示例
# Sample App
演示 My SDK 的各种用法。
## 运行
```bash
./gradlew :sample-app:installDebug
```
## 示例清单
- **BasicUsageFragment**: 基础初始化与调用
- **AdvancedUsageFragment**: 自定义配置与并发操作
- **ErrorHandlingFragment**: 错误处理与重试策略
Quick Checklist
- Required Inputs 已填写并冻结(坐标、版本、兼容策略)
- Public API 最小化,只暴露必要接口
- 使用 internal/private 隐藏实现细节
- 多模块分层(api + core + optional modules)
- Consumer Proguard Rules 配置完成
- 依赖策略明确(api vs implementation vs compileOnly)
- groupId/artifactId/version 为单一来源
- Maven Central 发布流程配置完成
- Binary Compatibility Validator 纳入 CI
- Semantic Versioning 与 Deprecation 策略明确
- Dokka 文档生成配置完成
- KDoc 注释覆盖所有 Public API
- Sample App 展示所有核心用法
- CHANGELOG.md 记录所有版本变更
- Release Gate 命令(lint/test/assemble/apiCheck/dokka/publishToMavenLocal)通过
- 发布凭证仅来自 CI secret(仓库无明文密钥)