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

  1. 先确认 Required Inputs(group/artifact、最低支持、版本策略)
  2. 设计 Public API 与模块结构,并冻结 API surface
  3. 配置 Consumer Proguard 与依赖传递策略
  4. 设置发布流程(Maven Central / 私有仓库)与签章密钥
  5. 创建文档与 Sample App,补齐迁移与升级说明
  6. 运行 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 / jdkVersion
  • Public 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 一起分发
  • publish workflow(含签章、发布、失败回滚说明)
  • apiCheck workflow(PR 阶段执行)
  • Dokka 文档与 CHANGELOG.md
  • sample-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(仓库无明文密钥)
Weekly Installs
0
First Seen
Jan 1, 1970